mirror of
https://github.com/weyne85/rustdesk.git
synced 2025-10-29 17:00:05 +00:00
Merge pull request #1 from Heap-Hop/hwcodec
Update ARB(beta) and merge master
This commit is contained in:
commit
24245e7d3f
12
.github/workflows/winget.yml
vendored
Normal file
12
.github/workflows/winget.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
name: Publish to WinGet
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: windows-latest # action can only be run on windows
|
||||
steps:
|
||||
- uses: vedantmgoyal2009/winget-releaser@latest
|
||||
with:
|
||||
identifier: RustDesk.RustDesk
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
164
Cargo.lock
generated
164
Cargo.lock
generated
@ -123,9 +123,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.57"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
||||
|
||||
[[package]]
|
||||
name = "arboard"
|
||||
@ -455,7 +455,7 @@ version = "0.24.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb"
|
||||
dependencies = [
|
||||
"clap 3.1.18",
|
||||
"clap 3.2.6",
|
||||
"heck 0.4.0",
|
||||
"indexmap",
|
||||
"log",
|
||||
@ -553,9 +553,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.18"
|
||||
version = "3.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||
checksum = "9f1fe12880bae935d142c8702d500c63a4e8634b6c3c57ad72bf978fc7b6249a"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@ -568,9 +568,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.0"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||
checksum = "87eba3c8c7f42ef17f6c659fc7416d0f4758cd3e58861ee63c5fa4a4dde649e4"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
@ -876,9 +876,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.4"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
|
||||
checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
@ -897,15 +897,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.8"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c"
|
||||
checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"once_cell",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
@ -921,12 +921,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.8"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
|
||||
checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1751,13 +1751,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2123,9 +2123,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
|
||||
|
||||
[[package]]
|
||||
name = "hbb_common"
|
||||
@ -2335,9 +2335,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.2"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg 1.1.0",
|
||||
"hashbrown",
|
||||
@ -2425,9 +2425,9 @@ checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.57"
|
||||
version = "0.3.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
|
||||
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@ -2584,9 +2584,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -2757,13 +2757,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
|
||||
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"windows-sys 0.36.1",
|
||||
]
|
||||
|
||||
@ -3021,9 +3021,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790"
|
||||
checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19"
|
||||
dependencies = [
|
||||
"num-traits 0.2.15",
|
||||
]
|
||||
@ -3517,9 +3517,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.39"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -3648,9 +3648,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -3925,9 +3925,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.10"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
|
||||
checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes",
|
||||
@ -3947,12 +3947,13 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls",
|
||||
"rustls-pemfile 0.3.0",
|
||||
"rustls-pemfile 1.0.0",
|
||||
"serde 1.0.137",
|
||||
"serde_json 1.0.81",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
@ -4061,7 +4062,7 @@ dependencies = [
|
||||
"base64",
|
||||
"cc",
|
||||
"cfg-if 1.0.0",
|
||||
"clap 3.1.18",
|
||||
"clap 3.2.6",
|
||||
"clipboard",
|
||||
"cocoa 0.24.0",
|
||||
"core-foundation 0.9.3",
|
||||
@ -4164,15 +4165,6 @@ dependencies = [
|
||||
"base64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360"
|
||||
dependencies = [
|
||||
"base64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "1.0.0"
|
||||
@ -4194,9 +4186,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.6"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||
checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@ -4485,9 +4477,9 @@ checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
@ -4627,9 +4619,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.96"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4650,13 +4642,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sys-locale"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3913c5a3d30054d7f77cf07cdd800c8103ace15c6e44437c5db66a43dd3a92cf"
|
||||
checksum = "658ee915b6c7b73ec4c1ffcd838506b5c5a4087eadc1ec8f862f1066cf2c8132"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cstr_core",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
@ -4804,9 +4798,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.9"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
|
||||
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
||||
dependencies = [
|
||||
"itoa 1.0.2",
|
||||
"libc",
|
||||
@ -4844,7 +4838,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio 0.8.3",
|
||||
"mio 0.8.4",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot 0.12.1",
|
||||
@ -4880,7 +4874,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tokio-socks"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/open-trade/tokio-socks#3de8300fbce37e2cdaef042e016aa95058d007cf"
|
||||
source = "git+https://github.com/open-trade/tokio-socks#c34272f219b24dc6508f13fa81eff9850e616ce2"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"either",
|
||||
@ -4934,9 +4928,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
||||
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
@ -4963,9 +4957,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.27"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921"
|
||||
checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
@ -5040,15 +5034,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.19"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
|
||||
checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
@ -5161,12 +5155,6 @@ dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@ -5175,9 +5163,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.80"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
|
||||
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen-macro",
|
||||
@ -5185,9 +5173,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.80"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
|
||||
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
@ -5200,9 +5188,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.30"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2"
|
||||
checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
@ -5212,9 +5200,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.80"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
|
||||
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -5222,9 +5210,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.80"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
|
||||
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5235,9 +5223,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.80"
|
||||
version = "0.2.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
|
||||
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
@ -5314,9 +5302,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.57"
|
||||
version = "0.3.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283"
|
||||
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
||||
190
README-AR.md
Normal file
190
README-AR.md
Normal file
@ -0,0 +1,190 @@
|
||||
<p align="center">
|
||||
<img src="logo-header.svg" alt="RustDesk - Your remote desktop"><br>
|
||||
<a href="#free-public-servers">Servers</a> •
|
||||
<a href="#raw-steps-to-build">Build</a> •
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b> لغتك الأم, <a href="https://github.com/rustdesk/doc.rustdesk.com">Doc</a> و <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk UI</a>, README نحن بحاجة إلى مساعدتك لترجمة هذا </b>
|
||||
</p>
|
||||
|
||||
[Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk) :تواصل معنا عبر
|
||||
|
||||
[](https://ko-fi.com/I2I04VU09)
|
||||
|
||||
.Rustبرنامج آخر لسطح المكتب عن بعد، مكتوب بـ
|
||||
يعمل خارج الصندوق، لا حاجة إلى إعدادات. لديك سيطرة كاملة على بياناتك، دون مخاوف بشأن الأمن. يمكنك استخدام خادم
|
||||
الخاص بنا rendezvous/relay
|
||||
[جهز لنفسك واحدا](https://rustdesk.com/server), أو
|
||||
[خاص بك rendezvous/relay أكتب خادم](https://github.com/rustdesk/rustdesk-server-demo).
|
||||
|
||||

|
||||
|
||||
لمساعدتك على ذلك [`CONTRIBUTING.md`](CONTRIBUTING.md) يرحب بمساهمة الجميع. اطلع على RustDesk.
|
||||
|
||||
[**؟ RustDesk كيفية يعمل**](https://github.com/rustdesk/rustdesk/wiki/How-does-RustDesk-work%3F)
|
||||
|
||||
[**BINARY تنزيل**](https://github.com/rustdesk/rustdesk/releases)
|
||||
|
||||
## خوادم مفتوحة ومجانية
|
||||
|
||||
فيما يلي الخوادم التي تستخدمها مجانًا، وقد تتغير طوال الوقت. إذا لم تكن قريبًا من أحد هؤلاء، فقد تكون شبكتك بطيئة.
|
||||
| الموقع | المورد | المواصفات |
|
||||
| --------- | ------------- | ------------------ |
|
||||
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
|
||||
| Singapore | Vultr | 1 VCPU / 1GB RAM |
|
||||
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
|
||||
|
||||
## التبعيات
|
||||
|
||||
لواجهة المستخدم الرسومية [sciter](https://sciter.com/) نسخة سطح المكتب تستخدم
|
||||
بنفسك sciter dynamic library عليك تحميل
|
||||
|
||||
[Windows](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.win/x64/sciter.dll) |
|
||||
[Linux](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so) |
|
||||
[MacOS](https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.osx/libsciter.dylib)
|
||||
|
||||
Sciter إلى Flutter سنقوم بترحيل نسخة سطح المكتب من .Flutter تستخدم إصدارات الهاتف المحمول.
|
||||
|
||||
## خطوات البناء
|
||||
|
||||
- C++ build env و Rust development env قم بإعداد
|
||||
|
||||
- بطريقة صحيحة `VCPKG_ROOT` env variable وأعد [vcpkg](https://github.com/microsoft/vcpkg) ثبت
|
||||
|
||||
- Windows: `vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static`
|
||||
- Linux/MacOS: `vcpkg install libvpx libyuv opus`
|
||||
|
||||
- run `cargo run`
|
||||
|
||||
## [البناء](https://rustdesk.com/docs/en/dev/build/)
|
||||
|
||||
## Linux
|
||||
|
||||
### Ubuntu 18 (Debian 10)
|
||||
|
||||
```sh
|
||||
sudo apt install -y g++ gcc git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake
|
||||
```
|
||||
|
||||
### Fedora 28 (CentOS 8)
|
||||
|
||||
```sh
|
||||
sudo yum -y install gcc-c++ git curl wget nasm yasm gcc gtk3-devel clang libxcb-devel libxdo-devel libXfixes-devel pulseaudio-libs-devel cmake alsa-lib-devel
|
||||
```
|
||||
|
||||
### Arch (Manjaro)
|
||||
|
||||
```sh
|
||||
sudo pacman -Syu --needed unzip git cmake gcc curl wget yasm nasm zip make pkg-config clang gtk3 xdotool libxcb libxfixes alsa-lib pulseaudio
|
||||
```
|
||||
|
||||
### pynput package تثبيت
|
||||
|
||||
```sh
|
||||
pip3 install pynput
|
||||
```
|
||||
|
||||
### vcpkg تثبيت
|
||||
|
||||
```sh
|
||||
git clone https://github.com/microsoft/vcpkg
|
||||
cd vcpkg
|
||||
git checkout 2021.12.01
|
||||
cd ..
|
||||
vcpkg/bootstrap-vcpkg.sh
|
||||
export VCPKG_ROOT=$HOME/vcpkg
|
||||
vcpkg/vcpkg install libvpx libyuv opus
|
||||
```
|
||||
|
||||
### Fix libvpx (For Fedora)
|
||||
|
||||
```sh
|
||||
cd vcpkg/buildtrees/libvpx/src
|
||||
cd *
|
||||
./configure
|
||||
sed -i 's/CFLAGS+=-I/CFLAGS+=-fPIC -I/g' Makefile
|
||||
sed -i 's/CXXFLAGS+=-I/CXXFLAGS+=-fPIC -I/g' Makefile
|
||||
make
|
||||
cp libvpx.a $HOME/vcpkg/installed/x64-linux/lib/
|
||||
cd
|
||||
```
|
||||
|
||||
### البناء
|
||||
|
||||
```sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
source $HOME/.cargo/env
|
||||
git clone https://github.com/rustdesk/rustdesk
|
||||
cd rustdesk
|
||||
mkdir -p target/debug
|
||||
wget https://raw.githubusercontent.com/c-smile/sciter-sdk/master/bin.lnx/x64/libsciter-gtk.so
|
||||
mv libsciter-gtk.so target/debug
|
||||
VCPKG_ROOT=$HOME/vcpkg cargo run
|
||||
```
|
||||
|
||||
### X11 (Xorg) إلى Wayland تغيير
|
||||
|
||||
افتراضية GNOME session ك Xorg إتبع [هذه](https://docs.fedoraproject.org/en-US/quick-docs/configuring-xorg-as-default-gnome-session/) الخطوات لإعداد Wayland لا تدعم RustDesk
|
||||
|
||||
## Docker طريقة البناء باستخدام
|
||||
|
||||
ابدأ باستنساخ المستودع وبناء الكونتاينر:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/rustdesk/rustdesk
|
||||
cd rustdesk
|
||||
docker build -t "rustdesk-builder" .
|
||||
```
|
||||
|
||||
ثم، في كل مرة تحتاج إلى بناء التطبيق، قم بتشغيل الأمر التالي:
|
||||
|
||||
```sh
|
||||
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
|
||||
```
|
||||
|
||||
لاحظ أن البناء الأول قد يستغرق وقتًا أطول قبل تخزين التبعيات، وسيكون البناء اللاحق أسرع. بالإضافة إلى ذلك، إذا كنت بحاجة إلى تحديد وسائط مختلفة لأمر البناء، فيمكنك القيام بذلك في نهاية الأمر بوضع
|
||||
`<OPTIONAL-ARGS>`
|
||||
على سبيل المثال، إذا كنت ترغب في بناء إصدار محسن، فستقوم بتشغيل الأمر أعلاه متبوعًا بـ
|
||||
`--release`
|
||||
:سيكون الملف القابل للتنفيذ الناتج متاحًا في مجلد تارغت، ويمكن تشغيله باستخدام
|
||||
|
||||
```sh
|
||||
target/debug/rustdesk
|
||||
```
|
||||
|
||||
:أو في حال قمت ببناء إصدار محسن
|
||||
|
||||
```sh
|
||||
target/release/rustdesk
|
||||
```
|
||||
|
||||
RustDesk يرجى التأكد من أنك تنفذ هذه الأوامر من جذر مستودع
|
||||
وإلا فقد لا يتمكن التطبيق من العثور على الموارد المطلوبة. لاحظ أيضًا أن الأوامر الفرعية الأخرى مثل
|
||||
`install` أو `run`
|
||||
لا يتم دعمها حاليًا عبر هذه الطريقة لأنها ستقوم بتثبيت أو تشغيل البرنامج داخل الكونتاينر بدلاً من الهوست.
|
||||
|
||||
## هيكل الملف
|
||||
|
||||
- **[libs/hbb_common](https://github.com/rustdesk/rustdesk/tree/master/libs/hbb_common)**: وظائف لنقل الملفات، وبعض وظائف المرافق الأخرى tcp/udp، protobuf ترميز الفيديو، إعدادات
|
||||
|
||||
- **[libs/scrap](https://github.com/rustdesk/rustdesk/tree/master/libs/scrap)**: التقاط الشاشة
|
||||
- **[libs/enigo](https://github.com/rustdesk/rustdesk/tree/master/libs/enigo)**: التحكم في لوحة المفاتيح/الماوس الخاصة بكل منصة
|
||||
- **[src/ui](https://github.com/rustdesk/rustdesk/tree/master/src/ui)**: واجهة المستخدم الرسومية
|
||||
- **[src/server](https://github.com/rustdesk/rustdesk/tree/master/src/server)**: خدمات الصوت/الحافظة/المدخلات/الفيديو، ووصلات الشبكة
|
||||
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: بدء اتصال متقارن
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: أو المنقول عن بُعد (TCP hole punching) انتظر الاتصال المباشر [rustdesk-server](https://github.com/rustdesk/rustdesk-server) الإتصال ب
|
||||
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: رمز خاص بكل منصة
|
||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: رمز الهاتف المحمول
|
||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**:Flutter لعميل الويب الخاص ب Javascript
|
||||
|
||||
## لقطات
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Struktura</a> •
|
||||
<a href="#snapshot">Ukázky</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Potřebujeme Vaši pomoc s překláním textů tohoto ČTIMNE, <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">uživatelského rozhraní aplikace RustDesk</a> a <a href="https://github.com/rustdesk/doc.rustdesk.com">dokumentace k ní</a> do vašeho jazyka</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#auf-docker-kompilieren">Docker</a> •
|
||||
<a href="#dateistruktur">Dateistruktur</a> •
|
||||
<a href="#screenshots">Screenshots</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Wir brauchen deine Hilfe um diese README Datei zu verbessern und aktualisieren</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#kiel-kompili-kun-docker">Docker</a> •
|
||||
<a href="#dosierstrukturo">Strukturo</a> •
|
||||
<a href="#ekrankopio">Ekrankopio</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Ni bezonas helpon traduki tiun README kaj <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">la interfacon</a> al via denaska lingvo</b>
|
||||
</p>
|
||||
|
||||
|
||||
20
README-ES.md
20
README-ES.md
@ -5,11 +5,11 @@
|
||||
<a href="#como-compilar-con-docker">Docker</a> •
|
||||
<a href="#estructura-de-archivos">Estructura</a> •
|
||||
<a href="#captura-de-pantalla">Captura de pantalla</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Necesitamos tu ayuda para traducir este README a tu idioma</b>
|
||||
</p>
|
||||
|
||||
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
Chatea con nosotros: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
|
||||
[](https://ko-fi.com/I2I04VU09)
|
||||
|
||||
@ -23,9 +23,11 @@ RustDesk agradece la contribución de todo el mundo. Ve [`CONTRIBUTING.md`](CONT
|
||||
|
||||
A continuación se muestran los servidores que está utilizando de forma gratuita, puede cambiar en algún momento. Si no estás cerca de uno de ellos, tu red puede ser lenta.
|
||||
|
||||
- Seoul, AWS lightsail, 1 VCPU/0.5G RAM
|
||||
- Singapore, Vultr, 1 VCPU/1G RAM
|
||||
- Dallas, Vultr, 1 VCPU/1G RAM
|
||||
| Ubicación | Vendedor | Especificación |
|
||||
| --------- | ------------- | ------------------ |
|
||||
| Seoul | AWS lightsail | 1 VCPU / 0.5GB RAM |
|
||||
| Singapore | Vultr | 1 VCPU / 1GB RAM |
|
||||
| Dallas | Vultr | 1 VCPU / 1GB RAM | |
|
||||
|
||||
## Dependencies
|
||||
|
||||
@ -37,7 +39,7 @@ La versión Desktop usa [sciter](https://sciter.com/) para GUI, por favor bajate
|
||||
|
||||
## Pasos para compilar desde el inicio
|
||||
|
||||
- Prepara el entono de desarrollode Rust y el entorno de compilación de C++ y Rust.
|
||||
- Prepara el entono de desarrollo de Rust y el entorno de compilación de C++ y Rust.
|
||||
|
||||
- Instala [vcpkg](https://github.com/microsoft/vcpkg), y configura la variable de entono `VCPKG_ROOT` correctamente.
|
||||
|
||||
@ -78,7 +80,7 @@ export VCPKG_ROOT=$HOME/vcpkg
|
||||
vcpkg/vcpkg install libvpx libyuv opus
|
||||
```
|
||||
|
||||
### Soluciona libvpx (For Fedora)
|
||||
### Soluciona libvpx (Para Fedora)
|
||||
|
||||
```sh
|
||||
cd vcpkg/buildtrees/libvpx/src
|
||||
@ -124,7 +126,7 @@ Entonces, cada vez que necesites compilar una modificación, ejecuta el siguient
|
||||
docker run --rm -it -v $PWD:/home/user/rustdesk -v rustdesk-git-cache:/home/user/.cargo/git -v rustdesk-registry-cache:/home/user/.cargo/registry -e PUID="$(id -u)" -e PGID="$(id -g)" rustdesk-builder
|
||||
```
|
||||
|
||||
Ten en cuenta que la primera compilación puede tardar más tiempo antes de que las dependencias se almacenen en la caché, las siguientes compilaciones serán más rápidas. Además, si necesitas especificar diferentes argumentos a la orden de compilación, puede hacerlo al final de la linea de comandos en el apartado`<OPTIONAL-ARGS>`. Por ejemplo, si desea compilar una versión optimizada para publicación, deberá ejecutar el comando anterior seguido de `--release`. El ejecutable resultante estará disponible en la carpeta de destino en su sistema, y puede ser ejecutado con:
|
||||
Ten en cuenta que la primera compilación puede tardar más tiempo antes de que las dependencias se almacenen en la caché, las siguientes compilaciones serán más rápidas. Además, si necesitas especificar diferentes argumentos a la orden de compilación, puede hacerlo al final de la linea de comandos en el apartado `<OPTIONAL-ARGS>`. Por ejemplo, si desea compilar una versión optimizada para publicación, deberá ejecutar el comando anterior seguido de `--release`. El ejecutable resultante estará disponible en la carpeta de destino en su sistema, y puede ser ejecutado con:
|
||||
|
||||
```sh
|
||||
target/debug/rustdesk
|
||||
@ -148,6 +150,8 @@ Por favor, asegurate de que estás ejecutando estos comandos desde la raíz del
|
||||
- **[src/client.rs](https://github.com/rustdesk/rustdesk/tree/master/src/client.rs)**: iniciar una conexión "peer to peer"
|
||||
- **[src/rendezvous_mediator.rs](https://github.com/rustdesk/rustdesk/tree/master/src/rendezvous_mediator.rs)**: Comunicación con [rustdesk-server](https://github.com/rustdesk/rustdesk-server), esperar la conexión remota directa ("TCP hole punching") o conexión indirecta ("relayed")
|
||||
- **[src/platform](https://github.com/rustdesk/rustdesk/tree/master/src/platform)**: código específico de cada plataforma
|
||||
- **[flutter](https://github.com/rustdesk/rustdesk/tree/master/flutter)**: Flutter, código para moviles
|
||||
- **[flutter/web/js](https://github.com/rustdesk/rustdesk/tree/master/flutter/web/js)**: Javascript para cliente web Flutter
|
||||
|
||||
## Captura de pantalla
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a dir="rtl" href="#نحوه-ساخت-با-داکر">داکر</a> •
|
||||
<a dir="rtl" href="#ساخت">ساخت</a> •
|
||||
<a dir="rtl" href="#سرورهای-عمومی-رایگان">سرور</a><br>
|
||||
[<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
‫<b>برای ترجمه این <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang"> RustDesk UI</a> ،README و <a href="https://github.com/rustdesk/doc.rustdesk.com">Doc</a> به زبان مادری شما به کمکتون نیاز داریم
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Rakenne</a> •
|
||||
<a href="#snapshot">Tilannevedos</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Tarvitsemme apua tämän README-tiedoston kääntämiseksi äidinkielellesi</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#comment-construire-avec-docker">Docker</a> -
|
||||
<a href="#structure-du-projet">Structure</a> -
|
||||
<a href="#images">Images</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Nous avons besoin de votre aide pour traduire ce README dans votre langue maternelle</b>.
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Kami membutuhkan bantuan Anda untuk menerjemahkan README ini dan <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk UI</a> ke bahasa asli anda</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#come-compilare-con-docker">Docker</a> •
|
||||
<a href="#struttura-dei-file">Struttura</a> •
|
||||
<a href="#screenshots">Screenshots</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Abbiamo bisogno del tuo aiuto per tradurre questo README e la <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk UI</a> nella tua lingua nativa</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>このREADMEをあなたの母国語に翻訳するために、あなたの助けが必要です。</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>README를 모국어로 번역하기 위한 당신의 도움의 필요합니다.</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>ഈ README നിങ്ങളുടെ മാതൃഭാഷയിലേക്ക് വിവർത്തനം ചെയ്യാൻ ഞങ്ങൾക്ക് നിങ്ങളുടെ സഹായം ആവശ്യമാണ്</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structuur</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>We hebben je hulp nodig om deze README te vertalen naar jouw moedertaal</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#jak-kompilować-za-pomocą-dockera">Docker</a> •
|
||||
<a href="#struktura-plików">Struktura</a> •
|
||||
<a href="#migawkisnapshoty">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Potrzebujemy twojej pomocy w tłumaczeniu README na twój ojczysty język</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#como-compilar-com-docker">Docker</a> •
|
||||
<a href="#estrutura-de-arquivos">Estrutura</a> •
|
||||
<a href="#screenshots">Screenshots</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Precisamos de sua ajuda para traduzir este README e a <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">UI do RustDesk</a> para sua língua nativa</b>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>Нам нужна ваша помощь для перевода этого README и <a href="https://github.com/rustdesk/rustdesk/tree/master/src/rustdesk/tree/master/src/lang">RustDesk UI</a> на ваш родной язык</B>
|
||||
</p>
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<a href="#使用Docker编译">Docker</a> •
|
||||
<a href="#文件结构">结构</a> •
|
||||
<a href="#截图">截图</a><br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
</p>
|
||||
|
||||
Chat with us: [知乎](https://www.zhihu.com/people/rustdesk) | [Discord](https://discord.gg/nDceKgxnkV) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
|
||||
@ -5,13 +5,12 @@
|
||||
<a href="#how-to-build-with-docker">Docker</a> •
|
||||
<a href="#file-structure">Structure</a> •
|
||||
<a href="#snapshot">Snapshot</a><br>
|
||||
[<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>]<br>
|
||||
[<a href="README-CS.md">česky</a>] | [<a href="README-ZH.md">中文</a>] | [<a href="README-ES.md">Español</a>] | [<a href="README-FA.md">فارسی</a>] | [<a href="README-FR.md">Français</a>] | [<a href="README-DE.md">Deutsch</a>] | [<a href="README-PL.md">Polski</a>] | [<a href="README-ID.md">Indonesian</a>] | [<a href="README-FI.md">Suomi</a>] | [<a href="README-ML.md">മലയാളം</a>] | [<a href="README-JP.md">日本語</a>] | [<a href="README-NL.md">Nederlands</a>] | [<a href="README-IT.md">Italiano</a>] | [<a href="README-RU.md">Русский</a>] | [<a href="README-PTBR.md">Português (Brasil)</a>] | [<a href="README-EO.md">Esperanto</a>] | [<a href="README-KR.md">한국어</a>] | [<a href="README-AR.md">العربي</a>]<br>
|
||||
<b>We need your help to translate this README, <a href="https://github.com/rustdesk/rustdesk/tree/master/src/lang">RustDesk UI</a> and <a href="https://github.com/rustdesk/doc.rustdesk.com">Doc</a> to your native language</b>
|
||||
</p>
|
||||
|
||||
Chat with us: [Discord](https://discord.gg/nDceKgxnkV) | [Twitter](https://twitter.com/rustdesk) | [Reddit](https://www.reddit.com/r/rustdesk)
|
||||
|
||||
|
||||
[](https://ko-fi.com/I2I04VU09)
|
||||
|
||||
Yet another remote desktop software, written in Rust. Works out of the box, no configuration required. You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, [set up your own](https://rustdesk.com/server), or [write your own rendezvous/relay server](https://github.com/rustdesk/rustdesk-server-demo).
|
||||
@ -24,6 +23,10 @@ RustDesk welcomes contribution from everyone. See [`CONTRIBUTING.md`](CONTRIBUTI
|
||||
|
||||
[**BINARY DOWNLOAD**](https://github.com/rustdesk/rustdesk/releases)
|
||||
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/en/packages/com.carriez.flutter_hbb)
|
||||
|
||||
## Free Public Servers
|
||||
|
||||
Below are the servers you are using for free, it may change along the time. If you are not close to one of these, your network may be slow.
|
||||
|
||||
@ -1 +1,11 @@
|
||||
Yet another remote desktop software, written in Rust. Works out of the box, no configuration required. You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, <a href="https://rustdesk.com/server">set up your own</a>, or <a href="https://github.com/rustdesk/rustdesk-server-demo">write your own rendezvous/relay server</a>.
|
||||
An open-source remote desktop application, the open source TeamViewer alternative.
|
||||
Source code: https://github.com/rustdesk/rustdesk
|
||||
Doc: https://rustdesk.com/docs/en/manual/mobile/
|
||||
|
||||
In order for a remote device to control your Android device via mouse or touch, you need to allow RustDesk to use the "Accessibility" service, RustDesk uses AccessibilityService API to implement Addroid remote control.
|
||||
|
||||
In addtion to remote control, you can also transfer files between Android devices and PCs easily with RustDesk.
|
||||
|
||||
You have full control of your data, with no concerns about security. You can use our rendezvous/relay server, or self-hosting, or write your own rendezvous/relay server. Self-hosting server is free and open source: https://github.com/rustdesk/rustdesk-server
|
||||
|
||||
Please download and install desktop version from: https://rustdesk.com, then you can access and control your desktop from your mobile, or control your mobile from desktop.
|
||||
|
||||
@ -1 +1 @@
|
||||
Yet another remote desktop software
|
||||
An open-source remote desktop application, the open source TeamViewer alternative.
|
||||
|
||||
@ -1,3 +1,12 @@
|
||||
远程桌面软件,开箱即用,无需任何配置。您完全掌控数据,不用担心安全问题。您可以使用我们的注册/中继服务器,
|
||||
或者<a href="https://rustdesk.com/server">自己设置</a>,
|
||||
亦或者<a href="https://github.com/rustdesk/rustdesk-server-demo">开发您的版本</a>。
|
||||
开源远程桌面应用,开源 TeamViewer 替代方案。
|
||||
源代码:https://github.com/rustdesk/rustdesk
|
||||
文档:https://rustdesk.com/docs/en/manual/mobile/
|
||||
|
||||
为了让远程设备通过鼠标或触摸控制您的 Android 设备,您需要允许 RustDesk 使用“Accessibility”服务,RustDesk 使用 AccessibilityService API 来实现 Addroid 远程控制。
|
||||
|
||||
除了远程控制,您还可以使用 RustDesk 在 Android 设备和 PC 之间轻松传输文件。
|
||||
|
||||
您完全掌控数据,不用担心安全问题。您可以使用我们的注册/中继服务器,或者自建,亦或者开发您的版本。
|
||||
自托管服务器是免费和开源的:https://github.com/rustdesk/rustdesk-server
|
||||
|
||||
请从:https://rustdesk.com 下载并安装桌面版,然后您可以通过手机访问和控制您的桌面,或从桌面控制您的手机。
|
||||
|
||||
@ -1 +1 @@
|
||||
远程桌面软件
|
||||
开源远程桌面应用,开源 TeamViewer 替代方案
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# Required:
|
||||
# 1. set VCPKG_ROOT / ANDROID_NDK path environment variables
|
||||
# 2. vcpkg initialized
|
||||
# 3. ndk >= 22 (if ndk< 22 you need to change LD as `export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld`)
|
||||
# 3. ndk, version: 22 (if ndk < 22 you need to change LD as `export LD=$TOOLCHAIN/bin/$NDK_LLVM_TARGET-ld`)
|
||||
|
||||
if [ -z "$ANDROID_NDK" ]; then
|
||||
echo "Failed! Please set ANDROID_NDK"
|
||||
@ -16,66 +16,110 @@ if [ -z "$VCPKG_ROOT" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PREFIX=$VCPKG_ROOT/installed/arm64-android/
|
||||
API_LEVEL="21"
|
||||
|
||||
echo "*** [Start] Build opus / libyuv from vcpkg"
|
||||
export ANDROID_NDK_HOME=$ANDROID_NDK
|
||||
pushd $VCPKG_ROOT
|
||||
$VCPKG_ROOT/vcpkg install opus --triplet arm64-android
|
||||
$VCPKG_ROOT/vcpkg install libyuv --triplet arm64-android
|
||||
popd
|
||||
echo "*** [Finished] Build opus / libyuv from vcpkg"
|
||||
# NDK llvm toolchain
|
||||
HOST_TAG="linux-x86_64" # current platform, set as `ls $ANDROID_NDK/toolchains/llvm/prebuilt/`
|
||||
TOOLCHAIN=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST_TAG
|
||||
|
||||
function build {
|
||||
ANDROID_ABI=$1
|
||||
VCPKG_TARGET=$2
|
||||
NDK_LLVM_TARGET=$3
|
||||
LIBVPX_TARGET=$4
|
||||
|
||||
PREFIX=$VCPKG_ROOT/installed/$VCPKG_TARGET/
|
||||
|
||||
# 1
|
||||
echo "*** [$ANDROID_ABI][Start] Build opus / libyuv from vcpkg"
|
||||
export ANDROID_NDK_HOME=$ANDROID_NDK
|
||||
pushd $VCPKG_ROOT
|
||||
$VCPKG_ROOT/vcpkg install opus --triplet $VCPKG_TARGET
|
||||
$VCPKG_ROOT/vcpkg install libyuv --triplet $VCPKG_TARGET
|
||||
popd
|
||||
echo "*** [$ANDROID_ABI][Finished] Build opus / libyuv from vcpkg"
|
||||
|
||||
# 2
|
||||
echo "*** [$ANDROID_ABI][Start] Build libvpx"
|
||||
pushd build/libvpx
|
||||
export AR=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-ar
|
||||
export AS=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-as
|
||||
export LD=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-ld.gold # if ndk < 22, use aarch64-linux-android-ld
|
||||
export RANLIB=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-ranlib
|
||||
export STRIP=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}-strip
|
||||
|
||||
if [ $NDK_LLVM_TARGET == "arm-linux-androideabi" ]
|
||||
then
|
||||
export CC=$TOOLCHAIN/bin/armv7a-linux-androideabi${API_LEVEL}-clang
|
||||
export CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi${API_LEVEL}-clang++
|
||||
else
|
||||
export CC=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}${API_LEVEL}-clang
|
||||
export CXX=$TOOLCHAIN/bin/${NDK_LLVM_TARGET}${API_LEVEL}-clang++
|
||||
fi
|
||||
make clean
|
||||
./configure --target=$LIBVPX_TARGET \
|
||||
--enable-pic --disable-vp8 \
|
||||
--disable-webm-io \
|
||||
--disable-unit-tests \
|
||||
--disable-examples \
|
||||
--disable-libyuv \
|
||||
--disable-postproc \
|
||||
--disable-vp8 \
|
||||
--disable-tools \
|
||||
--disable-docs \
|
||||
--prefix=$PREFIX
|
||||
make -j5
|
||||
make install
|
||||
|
||||
popd
|
||||
echo "*** [$ANDROID_ABI][Finished] Build libvpx"
|
||||
|
||||
# 3
|
||||
echo "*** [$ANDROID_ABI][Start] Build oboe"
|
||||
pushd build/oboe
|
||||
make clean
|
||||
cmake -DBUILD_SHARED_LIBS=true \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DANDROID_TOOLCHAIN=clang \
|
||||
-DANDROID_STL=c++_shared \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DANDROID_ABI=$ANDROID_ABI \
|
||||
-DANDROID_PLATFORM=android-$API_LEVEL
|
||||
make -j5
|
||||
make install
|
||||
mv $PREFIX/lib/$ANDROID_ABI/liboboe.a $PREFIX/lib/
|
||||
popd
|
||||
echo "*** [$ANDROID_ABI][Finished] Build oboe"
|
||||
|
||||
echo "*** [$ANDROID_ABI][All Finished]"
|
||||
}
|
||||
|
||||
echo "*** [Start] Build libvpx"
|
||||
git clone -b v1.11.0 --depth=1 https://github.com/webmproject/libvpx.git build/libvpx
|
||||
pushd build/libvpx
|
||||
export NDK=$ANDROID_NDK
|
||||
export HOST_TAG=linux-x86_64
|
||||
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
|
||||
export AR=$TOOLCHAIN/bin/aarch64-linux-android-ar
|
||||
export AS=$TOOLCHAIN/bin/aarch64-linux-android-as
|
||||
export CC=$TOOLCHAIN/bin/aarch64-linux-android21-clang
|
||||
export CXX=$TOOLCHAIN/bin/aarch64-linux-android21-clang++
|
||||
export LD=$TOOLCHAIN/bin/aarch64-linux-android-ld.gold # if ndk < 22, use aarch64-linux-android-ld
|
||||
export RANLIB=$TOOLCHAIN/bin/aarch64-linux-android-ranlib
|
||||
export STRIP=$TOOLCHAIN/bin/aarch64-linux-android-strip
|
||||
|
||||
./configure --target=arm64-android-gcc \
|
||||
--enable-pic --disable-vp8 \
|
||||
--disable-webm-io \
|
||||
--disable-unit-tests \
|
||||
--disable-examples \
|
||||
--disable-libyuv \
|
||||
--disable-postproc \
|
||||
--disable-vp8 \
|
||||
--disable-tools \
|
||||
--disable-docs \
|
||||
--prefix=$PREFIX
|
||||
make -j5
|
||||
make install
|
||||
|
||||
popd
|
||||
echo "*** [Finished] Build libvpx"
|
||||
|
||||
|
||||
echo "*** [Start] Build oboe"
|
||||
git clone -b 1.6.1 --depth=1 https://github.com/google/oboe build/oboe
|
||||
patch -d build/oboe -p1 < ../src/oboe.patch
|
||||
pushd build/oboe
|
||||
cmake -DBUILD_SHARED_LIBS=true \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DANDROID_TOOLCHAIN=clang \
|
||||
-DANDROID_STL=c++_shared \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||
-DANDROID_ABI=arm64-v8a \
|
||||
-DANDROID_PLATFORM=android-21
|
||||
make -j5
|
||||
make install
|
||||
mv $PREFIX/lib/arm64-v8a/liboboe.a $PREFIX/lib/
|
||||
popd
|
||||
echo "*** [Finished] Build oboe"
|
||||
echo "*** [All Finished]"
|
||||
patch -N -d build/oboe -p1 < ../src/oboe.patch
|
||||
|
||||
# VCPKG_TARGET ANDROID_ABI
|
||||
# arm64-android arm64-v8a
|
||||
# arm-android armeabi-v7a
|
||||
# x64-android x86_64
|
||||
# x86-android x86
|
||||
|
||||
# NDK_LLVM_TARGET
|
||||
# aarch64-linux-android
|
||||
# arm-linux-androideabi
|
||||
# x86_64-linux-android
|
||||
# i686-linux-android
|
||||
|
||||
# LIBVPX_TARGET :
|
||||
# arm64-android-gcc
|
||||
# armv7-android-gcc
|
||||
# x86_64-android-gcc
|
||||
# x86-android-gcc
|
||||
|
||||
# args: ANDROID_ABI VCPKG_TARGET NDK_LLVM_TARGET LIBVPX_TARGET
|
||||
build arm64-v8a arm64-android aarch64-linux-android arm64-android-gcc
|
||||
build armeabi-v7a arm-android arm-linux-androideabi armv7-android-gcc
|
||||
|
||||
# rm -rf build/libvpx
|
||||
# rm -rf build/oboe
|
||||
@ -233,7 +233,7 @@ class AccessibilityListener extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
onPointerUp: (evt) {
|
||||
if (evt.size == 1 && GestureBinding.instance != null) {
|
||||
if (evt.size == 1) {
|
||||
GestureBinding.instance.handlePointerEvent(PointerUpEvent(
|
||||
pointer: evt.pointer + offset,
|
||||
size: 0.1,
|
||||
@ -243,7 +243,7 @@ class AccessibilityListener extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
onPointerMove: (evt) {
|
||||
if (evt.size == 1 && GestureBinding.instance != null) {
|
||||
if (evt.size == 1) {
|
||||
GestureBinding.instance.handlePointerEvent(PointerMoveEvent(
|
||||
pointer: evt.pointer + offset,
|
||||
size: 0.1,
|
||||
|
||||
@ -593,15 +593,7 @@ class FileFetcher {
|
||||
|
||||
tryCompleteTask(String? msg, String? isLocalStr) {
|
||||
if (msg == null || isLocalStr == null) return;
|
||||
late final isLocal;
|
||||
late final tasks;
|
||||
if (isLocalStr == "true") {
|
||||
isLocal = true;
|
||||
} else if (isLocalStr == "false") {
|
||||
isLocal = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final fd = FileDirectory.fromJson(jsonDecode(msg));
|
||||
if (fd.id > 0) {
|
||||
|
||||
@ -21,7 +21,6 @@ typedef F2 = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>);
|
||||
typedef F3 = void Function(Pointer<Utf8>, Pointer<Utf8>);
|
||||
|
||||
class PlatformFFI {
|
||||
static Pointer<RgbaFrame>? _lastRgbaFrame;
|
||||
static String _dir = '';
|
||||
static String _homeDir = '';
|
||||
static F2? _getByName;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:js';
|
||||
|
||||
@ -100,8 +100,8 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
: InkWell(
|
||||
onTap: () async {
|
||||
final url = _updateUrl + '.apk';
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
|
||||
@ -126,7 +126,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||
common < oldValue.length &&
|
||||
common < newValue.length &&
|
||||
newValue[common] == oldValue[common];
|
||||
++common);
|
||||
++common) {}
|
||||
for (i = 0; i < oldValue.length - common; ++i) {
|
||||
FFI.inputKey('VK_BACK');
|
||||
}
|
||||
|
||||
@ -68,8 +68,8 @@ class _SettingsState extends State<SettingsPage> {
|
||||
tiles: [
|
||||
SettingsTile.navigation(
|
||||
onPressed: (context) async {
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
},
|
||||
title: Text(translate("Version: ") + version),
|
||||
@ -105,8 +105,8 @@ void showAbout() {
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
const url = 'https://rustdesk.com/';
|
||||
if (await canLaunch(url)) {
|
||||
await launch(url);
|
||||
if (await canLaunchUrl(Uri.parse(url))) {
|
||||
await launchUrl(Uri.parse(url));
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
@ -149,7 +149,7 @@ fetch('http://localhost:21114/api/login', {
|
||||
'uuid': FFI.getByName('uuid')
|
||||
};
|
||||
try {
|
||||
final response = await http.post(Uri.parse('${url}/api/login'),
|
||||
final response = await http.post(Uri.parse('$url/api/login'),
|
||||
headers: {"Content-Type": "application/json"}, body: json.encode(body));
|
||||
return parseResp(response.body);
|
||||
} catch (e) {
|
||||
@ -186,7 +186,7 @@ void refreshCurrentUser() async {
|
||||
'uuid': FFI.getByName('uuid')
|
||||
};
|
||||
try {
|
||||
final response = await http.post(Uri.parse('${url}/api/currentUser'),
|
||||
final response = await http.post(Uri.parse('$url/api/currentUser'),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer $token"
|
||||
@ -212,7 +212,7 @@ void logout() async {
|
||||
'uuid': FFI.getByName('uuid')
|
||||
};
|
||||
try {
|
||||
await http.post(Uri.parse('${url}/api/logout'),
|
||||
await http.post(Uri.parse('$url/api/logout'),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer $token"
|
||||
@ -242,7 +242,7 @@ String getUrl() {
|
||||
url = 'http://${tmp[0]}:$port';
|
||||
}
|
||||
} else {
|
||||
url = 'http://${url}:21114';
|
||||
url = 'http://$url:21114';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,10 +594,7 @@ class _TapTracker {
|
||||
required this.entry,
|
||||
required Duration doubleTapMinTime,
|
||||
required this.gestureSettings,
|
||||
}) : assert(doubleTapMinTime != null),
|
||||
assert(event != null),
|
||||
assert(event.buttons != null),
|
||||
pointer = event.pointer,
|
||||
}) : pointer = event.pointer,
|
||||
_initialGlobalPosition = event.position,
|
||||
initialButtons = event.buttons,
|
||||
_doubleTapMinTimeCountdown =
|
||||
@ -643,7 +640,7 @@ class _TapTracker {
|
||||
/// CountdownZoned tracks whether the specified duration has elapsed since
|
||||
/// creation, honoring [Zone].
|
||||
class _CountdownZoned {
|
||||
_CountdownZoned({required Duration duration}) : assert(duration != null) {
|
||||
_CountdownZoned({required Duration duration}) {
|
||||
Timer(duration, _onTimeout);
|
||||
}
|
||||
|
||||
|
||||
@ -447,9 +447,9 @@ message PermissionInfo {
|
||||
|
||||
enum ImageQuality {
|
||||
NotSet = 0;
|
||||
Low = 2;
|
||||
Balanced = 3;
|
||||
Best = 4;
|
||||
Low = 50;
|
||||
Balanced = 66;
|
||||
Best = 100;
|
||||
}
|
||||
|
||||
message VideoCodecState {
|
||||
@ -481,6 +481,8 @@ message OptionMessage {
|
||||
message TestDelay {
|
||||
int64 time = 1;
|
||||
bool from_client = 2;
|
||||
uint32 last_delay = 3;
|
||||
uint32 target_bitrate = 4;
|
||||
}
|
||||
|
||||
message PublicKey {
|
||||
|
||||
@ -16,7 +16,7 @@ pub const RENDEZVOUS_TIMEOUT: u64 = 12_000;
|
||||
pub const CONNECT_TIMEOUT: u64 = 18_000;
|
||||
pub const REG_INTERVAL: i64 = 12_000;
|
||||
pub const COMPRESS_LEVEL: i32 = 3;
|
||||
const SERIAL: i32 = 1;
|
||||
const SERIAL: i32 = 3;
|
||||
// 128x128
|
||||
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
|
||||
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
|
||||
@ -140,6 +140,8 @@ pub struct PeerConfig {
|
||||
pub disable_clipboard: bool,
|
||||
#[serde(default)]
|
||||
pub enable_file_transfer: bool,
|
||||
#[serde(default)]
|
||||
pub show_quality_monitor: bool,
|
||||
|
||||
// the other scalar value must before this
|
||||
#[serde(default)]
|
||||
|
||||
@ -3,8 +3,8 @@ use crate::rgba_to_i420;
|
||||
use lazy_static::lazy_static;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::sync::Mutex;
|
||||
use std::{io, time::Duration};
|
||||
|
||||
lazy_static! {
|
||||
static ref SCREEN_SIZE: Mutex<(u16, u16, u16)> = Mutex::new((0, 0, 0)); // (width, height, scale)
|
||||
@ -33,7 +33,7 @@ impl Capturer {
|
||||
self.display.height() as usize
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&'a mut self, _timeout_ms: u32) -> io::Result<Frame<'a>> {
|
||||
pub fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result<Frame<'a>> {
|
||||
if let Some(buf) = get_video_raw() {
|
||||
crate::would_block_if_equal(&mut self.saved_raw_data, buf)?;
|
||||
rgba_to_i420(self.width(), self.height(), buf, &mut self.bgra);
|
||||
|
||||
@ -50,6 +50,8 @@ pub trait EncoderApi {
|
||||
fn encode_to_message(&mut self, frame: &[u8], ms: i64) -> ResultType<Message>;
|
||||
|
||||
fn use_yuv(&self) -> bool;
|
||||
|
||||
fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()>;
|
||||
}
|
||||
|
||||
pub struct DecoderCfg {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::dxgi;
|
||||
use std::io::ErrorKind::{NotFound, TimedOut, WouldBlock};
|
||||
use std::time::Duration;
|
||||
use std::{io, ops};
|
||||
|
||||
pub struct Capturer {
|
||||
@ -40,8 +41,8 @@ impl Capturer {
|
||||
self.height
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&'a mut self, timeout_ms: u32) -> io::Result<Frame<'a>> {
|
||||
match self.inner.frame(timeout_ms) {
|
||||
pub fn frame<'a>(&'a mut self, timeout_ms: Duration) -> io::Result<Frame<'a>> {
|
||||
match self.inner.frame(timeout_ms.as_millis() as _) {
|
||||
Ok(frame) => Ok(Frame(frame)),
|
||||
Err(ref error) if error.kind() == TimedOut => Err(WouldBlock.into()),
|
||||
Err(error) => Err(error),
|
||||
@ -135,7 +136,7 @@ impl CapturerMag {
|
||||
pub fn get_rect(&self) -> ((i32, i32), usize, usize) {
|
||||
self.inner.get_rect()
|
||||
}
|
||||
pub fn frame<'a>(&'a mut self, _timeout_ms: u32) -> io::Result<Frame<'a>> {
|
||||
pub fn frame<'a>(&'a mut self, _timeout_ms: Duration) -> io::Result<Frame<'a>> {
|
||||
self.inner.frame(&mut self.data)?;
|
||||
Ok(Frame(&self.data))
|
||||
}
|
||||
|
||||
@ -140,6 +140,10 @@ impl EncoderApi for HwEncoder {
|
||||
fn use_yuv(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl HwEncoder {
|
||||
|
||||
@ -119,17 +119,6 @@ impl EncoderApi for VpxEncoder {
|
||||
c.rc_target_bitrate = config.bitrate;
|
||||
c.rc_undershoot_pct = 95;
|
||||
c.rc_dropframe_thresh = 25;
|
||||
if config.rc_min_quantizer > 0 {
|
||||
c.rc_min_quantizer = config.rc_min_quantizer;
|
||||
}
|
||||
if config.rc_max_quantizer > 0 {
|
||||
c.rc_max_quantizer = config.rc_max_quantizer;
|
||||
}
|
||||
let mut speed = config.speed;
|
||||
if speed <= 0 {
|
||||
speed = 6;
|
||||
}
|
||||
|
||||
c.g_threads = if config.num_threads == 0 {
|
||||
num_cpus::get() as _
|
||||
} else {
|
||||
@ -174,7 +163,7 @@ impl EncoderApi for VpxEncoder {
|
||||
Higher numbers (7 or 8) will be lower quality but more manageable for lower latency
|
||||
use cases and also for lower CPU power devices such as mobile.
|
||||
*/
|
||||
call_vpx!(vpx_codec_control_(&mut ctx, VP8E_SET_CPUUSED as _, speed,));
|
||||
call_vpx!(vpx_codec_control_(&mut ctx, VP8E_SET_CPUUSED as _, 7,));
|
||||
// set row level multi-threading
|
||||
/*
|
||||
as some people in comments and below have already commented,
|
||||
@ -232,6 +221,13 @@ impl EncoderApi for VpxEncoder {
|
||||
fn use_yuv(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_bitrate(&mut self, bitrate: u32) -> ResultType<()> {
|
||||
let mut new_enc_cfg = unsafe { *self.ctx.config.enc.to_owned() };
|
||||
new_enc_cfg.rc_target_bitrate = bitrate;
|
||||
call_vpx!(vpx_codec_enc_config_set(&mut self.ctx, &new_enc_cfg));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
impl VpxEncoder {
|
||||
@ -336,9 +332,6 @@ pub struct VpxEncoderConfig {
|
||||
pub bitrate: c_uint,
|
||||
/// The codec
|
||||
pub codec: VpxVideoCodecId,
|
||||
pub rc_min_quantizer: u32,
|
||||
pub rc_max_quantizer: u32,
|
||||
pub speed: i32,
|
||||
pub num_threads: u32,
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::x11;
|
||||
use std::{io, ops};
|
||||
use std::{io, ops, time::Duration};
|
||||
|
||||
pub struct Capturer(x11::Capturer);
|
||||
|
||||
@ -16,7 +16,7 @@ impl Capturer {
|
||||
self.0.display().rect().h as usize
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&'a mut self, _timeout_ms: u32) -> io::Result<Frame<'a>> {
|
||||
pub fn frame<'a>(&'a mut self, _timeout: Duration) -> io::Result<Frame<'a>> {
|
||||
Ok(Frame(self.0.frame()?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,65 +1,32 @@
|
||||
from pynput.keyboard import Key, Controller
|
||||
from pynput.keyboard._xorg import KeyCode
|
||||
from pynput._util.xorg import display_manager
|
||||
import Xlib
|
||||
import os
|
||||
import sys
|
||||
import socket
|
||||
from Xlib.ext.xtest import fake_input
|
||||
from Xlib import X
|
||||
import Xlib
|
||||
|
||||
KeyCode._from_symbol("\0") # test
|
||||
|
||||
|
||||
class MyController(Controller):
|
||||
def _handle(self, key, is_press):
|
||||
"""Resolves a key identifier and sends a keyboard event.
|
||||
:param event: The *X* keyboard event.
|
||||
:param int keysym: The keysym to handle.
|
||||
"""
|
||||
event = Xlib.display.event.KeyPress if is_press \
|
||||
else Xlib.display.event.KeyRelease
|
||||
keysym = self._keysym(key)
|
||||
keycode = self._display.keysym_to_keycode(keysym)
|
||||
|
||||
# Make sure to verify that the key was resolved
|
||||
if keysym is None:
|
||||
raise self.InvalidKeyException(key)
|
||||
with display_manager(self._display) as dm:
|
||||
Xlib.ext.xtest.fake_input(
|
||||
dm,
|
||||
Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease,
|
||||
keycode)
|
||||
|
||||
# If the key has a virtual key code, use that immediately with
|
||||
# fake_input; fake input,being an X server extension, has access to
|
||||
# more internal state that we do
|
||||
if key.vk is not None:
|
||||
with display_manager(self._display) as dm:
|
||||
Xlib.ext.xtest.fake_input(
|
||||
dm,
|
||||
Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease,
|
||||
dm.keysym_to_keycode(key.vk))
|
||||
|
||||
# Otherwise use XSendEvent; we need to use this in the general case to
|
||||
# work around problems with keyboard layouts
|
||||
else:
|
||||
try:
|
||||
keycode, shift_state = self.keyboard_mapping[keysym]
|
||||
with self.modifiers as modifiers:
|
||||
alt_gr = Key.alt_gr in modifiers
|
||||
if alt_gr:
|
||||
self._send_key(event, keycode, shift_state)
|
||||
else:
|
||||
with display_manager(self._display) as dm:
|
||||
Xlib.ext.xtest.fake_input(
|
||||
dm,
|
||||
Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease,
|
||||
keycode)
|
||||
|
||||
except KeyError:
|
||||
with self._borrow_lock:
|
||||
keycode, index, count = self._borrows[keysym]
|
||||
self._send_key(
|
||||
event,
|
||||
keycode,
|
||||
index_to_shift(self._display, index))
|
||||
count += 1 if is_press else -1
|
||||
self._borrows[keysym] = (keycode, index, count)
|
||||
|
||||
# Notify any running listeners
|
||||
self._emit('_on_fake_event', key, is_press)
|
||||
|
||||
keyboard = MyController()
|
||||
|
||||
@ -77,7 +44,7 @@ server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
server.bind(server_address)
|
||||
server.listen(1)
|
||||
clientsocket, address = server.accept()
|
||||
os.system('chmod a+rw %s'%server_address)
|
||||
os.system('chmod a+rw %s' % server_address)
|
||||
print("Got pynput connection")
|
||||
|
||||
|
||||
@ -121,4 +88,3 @@ def loop():
|
||||
loop()
|
||||
clientsocket.close()
|
||||
server.close()
|
||||
|
||||
|
||||
@ -880,6 +880,8 @@ impl LoginConfigHandler {
|
||||
option.block_input = BoolOption::Yes.into();
|
||||
} else if name == "unblock-input" {
|
||||
option.block_input = BoolOption::No.into();
|
||||
} else if name == "show-quality-monitor" {
|
||||
config.show_quality_monitor = !config.show_quality_monitor;
|
||||
} else {
|
||||
let v = self.options.get(&name).is_some();
|
||||
if v {
|
||||
@ -912,15 +914,8 @@ impl LoginConfigHandler {
|
||||
n += 1;
|
||||
} else if q == "custom" {
|
||||
let config = PeerConfig::load(&self.id);
|
||||
let mut it = config.custom_image_quality.iter();
|
||||
let bitrate = it.next();
|
||||
let quantizer = it.next();
|
||||
if let Some(bitrate) = bitrate {
|
||||
if let Some(quantizer) = quantizer {
|
||||
msg.custom_image_quality = bitrate << 8 | quantizer;
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
msg.custom_image_quality = config.custom_image_quality[0] as _;
|
||||
n += 1;
|
||||
}
|
||||
if self.get_toggle_option("show-remote-cursor") {
|
||||
msg.show_remote_cursor = BoolOption::Yes.into();
|
||||
@ -987,6 +982,8 @@ impl LoginConfigHandler {
|
||||
self.config.disable_audio
|
||||
} else if name == "disable-clipboard" {
|
||||
self.config.disable_clipboard
|
||||
} else if name == "show-quality-monitor" {
|
||||
self.config.show_quality_monitor
|
||||
} else {
|
||||
!self.get_option(name).is_empty()
|
||||
}
|
||||
@ -1008,17 +1005,17 @@ impl LoginConfigHandler {
|
||||
msg_out
|
||||
}
|
||||
|
||||
pub fn save_custom_image_quality(&mut self, bitrate: i32, quantizer: i32) -> Message {
|
||||
pub fn save_custom_image_quality(&mut self, custom_image_quality: i32) -> Message {
|
||||
let mut misc = Misc::new();
|
||||
misc.set_option(OptionMessage {
|
||||
custom_image_quality: bitrate << 8 | quantizer,
|
||||
custom_image_quality,
|
||||
..Default::default()
|
||||
});
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_misc(misc);
|
||||
let mut config = self.load_config();
|
||||
config.image_quality = "custom".to_owned();
|
||||
config.custom_image_quality = vec![bitrate, quantizer];
|
||||
config.custom_image_quality = vec![custom_image_quality as _];
|
||||
self.save_config(config);
|
||||
msg_out
|
||||
}
|
||||
@ -1215,14 +1212,6 @@ where
|
||||
return (video_sender, audio_sender);
|
||||
}
|
||||
|
||||
pub async fn handle_test_delay(t: TestDelay, peer: &mut Stream) {
|
||||
if !t.from_client {
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_test_delay(t);
|
||||
allow_err!(peer.send(&msg_out).await);
|
||||
}
|
||||
}
|
||||
|
||||
// mask = buttons << 3 | type
|
||||
// type, 1: down, 2: up, 3: wheel
|
||||
// buttons, 1: left, 2: right, 4: middle
|
||||
|
||||
@ -6,6 +6,7 @@ mod da;
|
||||
mod sk;
|
||||
mod de;
|
||||
mod en;
|
||||
mod es;
|
||||
mod eo;
|
||||
mod fr;
|
||||
mod id;
|
||||
@ -44,6 +45,7 @@ pub fn translate_locale(name: String, locale: &str) -> String {
|
||||
"it" => it::T.deref(),
|
||||
"tw" => tw::T.deref(),
|
||||
"de" => de::T.deref(),
|
||||
"es" => es::T.deref(),
|
||||
"ru" => ru::T.deref(),
|
||||
"eo" => eo::T.deref(),
|
||||
"id" => id::T.deref(),
|
||||
|
||||
283
src/lang/es.rs
Normal file
283
src/lang/es.rs
Normal file
@ -0,0 +1,283 @@
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
[
|
||||
("Status", "Estado"),
|
||||
("Your Desktop", "Tu escritorio"),
|
||||
("desk_tip", "Puoi accedere al tuo desktop usando l'ID e la password riportati qui."),
|
||||
("Password", "Contraseña"),
|
||||
("Ready", "Listo"),
|
||||
("Established", "Establecido"),
|
||||
("connecting_status", "Conexión a la red RustDesk en progreso..."),
|
||||
("Enable Service", "Habilitar Servicio"),
|
||||
("Start Service", "Iniciar Servicio"),
|
||||
("Service is running", "Servicio se está ejecutando"),
|
||||
("Service is not running", "Servicio no se está ejecutando"),
|
||||
("not_ready_status", "No está listo. Comprueba tu conexión"),
|
||||
("Control Remote Desktop", "Controlar Escritorio Remoto"),
|
||||
("Transfer File", "Transferir archivo"),
|
||||
("Connect", "Conectar"),
|
||||
("Recent Sessions", "Sesiones recientes"),
|
||||
("Address Book", "Directorio"),
|
||||
("Confirmation", "Confirmación"),
|
||||
("TCP Tunneling", "Tunel TCP"),
|
||||
("Remove", "Remover"),
|
||||
("Refresh random password", "Actualizar contraseña aleatoria"),
|
||||
("Set your own password", "Establece tu propia contraseña"),
|
||||
("Enable Keyboard/Mouse", "Habilitar teclado/ratón"),
|
||||
("Enable Clipboard", "Habilitar portapapeles"),
|
||||
("Enable File Transfer", "Habilitar transferencia de archivos"),
|
||||
("Enable TCP Tunneling", "Habilitar tunel TCP"),
|
||||
("IP Whitelisting", "Lista blanca IP"),
|
||||
("ID/Relay Server", "Servidor de ID/Relay"),
|
||||
("Stop service", "Parar servicio"),
|
||||
("Change ID", "Cambiar identificación"),
|
||||
("Website", "Sitio web"),
|
||||
("About", "Sobre"),
|
||||
("Mute", "Silencio"),
|
||||
("Audio Input", "Entrada de audio"),
|
||||
("ID Server", "ID server"),
|
||||
("Relay Server", "Server relay"),
|
||||
("API Server", "Server API"),
|
||||
("invalid_http", "debe comenzar con http:// o https://"),
|
||||
("Invalid IP", "IP inválida"),
|
||||
("id_change_tip", "Solo puedes usar caracteres a-z, A-Z, 0-9 e _ (guion bajo). El primer carácter debe ser a-z o A-Z. La longitud debe estar entre 6 a 16 caracteres."),
|
||||
("Invalid format", "Formato inválido"),
|
||||
("server_not_support", "Aún no es compatible con el servidor"),
|
||||
("Not available", "Indisponible"),
|
||||
("Too frequent", "Demasiado frecuente"),
|
||||
("Cancel", "Cancelar"),
|
||||
("Skip", "Saltar"),
|
||||
("Close", "Cerrar"),
|
||||
("Retry", "Volver"),
|
||||
("OK", "OK"),
|
||||
("Password Required", "Se requiere contraseña"),
|
||||
("Please enter your password", "Por favor, introduzca su contraseña"),
|
||||
("Remember password", "Recordar contraseña"),
|
||||
("Wrong Password", "Contraseña incorrecta"),
|
||||
("Do you want to enter again?", "Quieres volver a entrar?"),
|
||||
("Connection Error", "Error de conexión"),
|
||||
("Error", "Error"),
|
||||
("Reset by the peer", "Restablecido por el par"),
|
||||
("Connecting...", "Conectando..."),
|
||||
("Connection in progress. Please wait.", "Conexión en curso. Espere por favor."),
|
||||
("Please try 1 minute later", "Intente 1 minuto más tarde"),
|
||||
("Login Error", "Error de inicio de sesión"),
|
||||
("Successful", "Exitoso"),
|
||||
("Connected, waiting for image...", "Conectado, esperando imagen..."),
|
||||
("Name", "Nombre"),
|
||||
("Type", "Tipo"),
|
||||
("Modified", "Modificado"),
|
||||
("Size", "Tamaño"),
|
||||
("Show Hidden Files", "Mostrar archivos ocultos"),
|
||||
("Receive", "Recibir"),
|
||||
("Send", "Enviar"),
|
||||
("Refresh File", "Actualizar archivo"),
|
||||
("Local", "Local"),
|
||||
("Remote", "Remoto"),
|
||||
("Remote Computer", "Computadora remota"),
|
||||
("Local Computer", "Computadora local"),
|
||||
("Confirm Delete", "Confirmar eliminación"),
|
||||
("Delete", "Borrar"),
|
||||
("Properties", "Propiedades"),
|
||||
("Multi Select", "Selección múltiple"),
|
||||
("Empty Directory", "Directorio vacío"),
|
||||
("Not an empty directory", "No es un directorio vacío"),
|
||||
("Are you sure you want to delete this file?", "Estás seguro de que quieres eliminar este archivo?"),
|
||||
("Are you sure you want to delete this empty directory?", "Está seguro de que desea eliminar este directorio vacío?"),
|
||||
("Are you sure you want to delete the file of this directory?", "Está seguro de que desea eliminar el archivo de este directorio?"),
|
||||
("Do this for all conflicts", "Haga esto para todos los conflictos"),
|
||||
("This is irreversible!", "Esto es irreversible!"),
|
||||
("Deleting", "Borrando"),
|
||||
("files", "archivos"),
|
||||
("Waiting", "Esperando"),
|
||||
("Finished", "Acabado"),
|
||||
("Speed", "Velocidad"),
|
||||
("Custom Image Quality", "Calidad de imagen personalizada"),
|
||||
("Privacy mode", "Modo privado"),
|
||||
("Block user input", "Bloquear entrada de usuario"),
|
||||
("Unblock user input", "Desbloquear entrada de usuario"),
|
||||
("Adjust Window", "Ajustar ventana"),
|
||||
("Original", "Original"),
|
||||
("Shrink", "Encogerse"),
|
||||
("Stretch", "Estirar"),
|
||||
("Good image quality", "Buena calidad de imagen"),
|
||||
("Balanced", "Equilibrado"),
|
||||
("Optimize reaction time", "Optimizar el tiempo de reacción"),
|
||||
("Custom", "Personalizado"),
|
||||
("Show remote cursor", "Mostrar cursor remoto"),
|
||||
("Disable clipboard", "Deshabilitar portapapeles"),
|
||||
("Lock after session end", "Bloquear después del final de la sesión"),
|
||||
("Insert", "Insertar"),
|
||||
("Insert Lock", "Insertar bloqueo"),
|
||||
("Refresh", "Actualizar"),
|
||||
("ID does not exist", "ID no existe"),
|
||||
("Failed to connect to rendezvous server", "No se pudo conectar al servidor de encuentro"),
|
||||
("Please try later", "Por favor intente mas tarde"),
|
||||
("Remote desktop is offline", "El escritorio remoto está fuera de línea"),
|
||||
("Key mismatch", "La clave no coincide"),
|
||||
("Timeout", "Timeout"),
|
||||
("Failed to connect to relay server", "No se pudo conectar al servidor de retransmisión"),
|
||||
("Failed to connect via rendezvous server", "No se pudo conectar a través del servidor de encuentro"),
|
||||
("Failed to connect via relay server", "No se pudo conectar a través del servidor de retransmisión"),
|
||||
("Failed to make direct connection to remote desktop", "No se pudo establecer la conexión directa con el escritorio remoto"),
|
||||
("Set Password", "Configurar la clave"),
|
||||
("OS Password", "Contraseña del sistema operativo"),
|
||||
("install_tip", "Debido al Control de cuentas de usuario, es posible que RustDesk no funcione correctamente como escritorio remoto. Para evitar este problema, haga clic en el botón de abajo para instalar RustDesk a nivel de sistema."),
|
||||
("Click to upgrade", "Clic para actualizar"),
|
||||
("Click to download", "Clic para descargar"),
|
||||
("Click to update", "Fare clic per aggiornare"),
|
||||
("Configure", "Configurar"),
|
||||
("config_acc", "Para controlar su escritorio desde el exterior, debe otorgar permiso a RustDesk de \"Accesibilidad\"."),
|
||||
("config_screen", "Para controlar su escritorio desde el exterior, debe otorgar permiso a RustDesk de \"Grabación de pantalla\"."),
|
||||
("Installing ...", "Instalando ..."),
|
||||
("Install", "Instalar"),
|
||||
("Installation", "Instalación"),
|
||||
("Installation Path", "Ruta de instalación"),
|
||||
("Create start menu shortcuts", "Crear accesos directos al menú de inicio"),
|
||||
("Create desktop icon", "Crear icono de escritorio"),
|
||||
("agreement_tip", "Al iniciar la instalación, acepta los términos del acuerdo de licencia."),
|
||||
("Accept and Install", "Aceptar e instalar"),
|
||||
("End-user license agreement", "Acuerdo de licencia de usuario final"),
|
||||
("Generating ...", "Generando ..."),
|
||||
("Your installation is lower version.", "Su instalación es una versión inferior."),
|
||||
("not_close_tcp_tip", "No cierre esta ventana mientras esté usando el túnel"),
|
||||
("Listening ...", "Escuchando ..."),
|
||||
("Remote Host", "Servidor remoto"),
|
||||
("Remote Port", "Puerto remoto"),
|
||||
("Action", "Acción"),
|
||||
("Add", "Agregar"),
|
||||
("Local Port", "Puerto local"),
|
||||
("setup_server_tip", "Para una conexión más rápida, configure su propio servidor"),
|
||||
("Too short, at least 6 characters.", "Demasiado corto, al menos 6 caracteres."),
|
||||
("The confirmation is not identical.", "La confirmación no es idéntica."),
|
||||
("Permissions", "Permisos"),
|
||||
("Accept", "Aceptar"),
|
||||
("Dismiss", "Cancelar"),
|
||||
("Disconnect", "Desconectar"),
|
||||
("Allow using keyboard and mouse", "Permitir el uso del teclado y el mouse"),
|
||||
("Allow using clipboard", "Permitir usar portapapeles"),
|
||||
("Allow hearing sound", "Permitir escuchar sonido"),
|
||||
("Allow file copy and paste", "Permitir copiar y pegar archivos"),
|
||||
("Connected", "Conectado"),
|
||||
("Direct and encrypted connection", "Conexión directa y encriptada"),
|
||||
("Relayed and encrypted connection", "Conexión retransmitida y cifrada"),
|
||||
("Direct and unencrypted connection", "Conexión directa y sin cifrar"),
|
||||
("Relayed and unencrypted connection", "Conexión retransmitida y sin cifrar"),
|
||||
("Enter Remote ID", "Ingrese el ID remoto"),
|
||||
("Enter your password", "Ingrese su contraseña"),
|
||||
("Logging in...", "Iniciando sesión..."),
|
||||
("Enable RDP session sharing", "Habilitar el uso compartido de sesiones RDP"),
|
||||
("Auto Login", "Ingreso automático"),
|
||||
("Enable Direct IP Access", "Habilitar acceso IP directo"),
|
||||
("Rename", "Renombrar"),
|
||||
("Space", "Espacio"),
|
||||
("Create Desktop Shortcut", "Crear acceso directo del escritorio"),
|
||||
("Change Path", "Cambiar ruta"),
|
||||
("Create Folder", "Crear carpeta"),
|
||||
("Please enter the folder name", "Por favor ingrese el nombre de la carpeta"),
|
||||
("Fix it", "Resolver"),
|
||||
("Warning", "Aviso"),
|
||||
("Login screen using Wayland is not supported", "La pantalla de inicio de sesión con Wayland no es compatible"),
|
||||
("Reboot required", "Reinicio requerido"),
|
||||
("Unsupported display server ", "Servidor de visualización no compatible"),
|
||||
("x11 expected", "x11 necesario"),
|
||||
("Port", "Puerto"),
|
||||
("Settings", "Ajustes"),
|
||||
("Username", " Nombre de usuario"),
|
||||
("Invalid port", "Puerto inválido"),
|
||||
("Closed manually by the peer", "Cerrado manualmente por el par"),
|
||||
("Enable remote configuration modification", "Habilitar modificación de configuración remota"),
|
||||
("Run without install", "Ejecutar sin instalar"),
|
||||
("Always connected via relay", "Siempre conectado a través de relay"),
|
||||
("Always connect via relay", "Conéctese siempre a través de relay"),
|
||||
("whitelist_tip", "Solo las direcciones IP autorizadas pueden conectarse a este escritorio"),
|
||||
("Login", "Iniciar sesión"),
|
||||
("Logout", "Salir"),
|
||||
("Tags", "Tags"),
|
||||
("Search ID", "Buscar ID"),
|
||||
("Current Wayland display server is not supported", "El servidor de visualización actual de Wayland no es compatible"),
|
||||
("whitelist_sep", "Separados por coma, punto y coma, espacio o nueva línea"),
|
||||
("Add ID", "Agregar ID"),
|
||||
("Add Tag", "Agregar tag"),
|
||||
("Unselect all tags", "Deseleccionar todos los tags"),
|
||||
("Network error", "Error de red"),
|
||||
("Username missed", "Olvidó su nombre de usuario"),
|
||||
("Password missed", "Olvidó su contraseña"),
|
||||
("Wrong credentials", "Credenciales incorrectas"),
|
||||
("Edit Tag", "Editar tag"),
|
||||
("Unremember Password", "Olvidaste tu contraseña"),
|
||||
("Favorites", "Favoritos"),
|
||||
("Add to Favorites", "Agregar a favoritos"),
|
||||
("Remove from Favorites", "Quitar de favoritos"),
|
||||
("Empty", "Vacío"),
|
||||
("Invalid folder name", "Nombre de carpeta no válido"),
|
||||
("Socks5 Proxy", "Proxy Socks5"),
|
||||
("Hostname", "Nombre de host"),
|
||||
("Discovered", "Descubierto"),
|
||||
("install_daemon_tip", "Para comenzar en el encendido, debe instalar el servicio del sistema."),
|
||||
("Remote ID", "ID remoto"),
|
||||
("Paste", "Pegar"),
|
||||
("Paste here?", "Pegar aqui?"),
|
||||
("Are you sure to close the connection?", "Estás seguro de cerrar la conexión?"),
|
||||
("Download new version", "Descargar nueva versión"),
|
||||
("Touch mode", "Modo táctil"),
|
||||
("Mouse mode", "Modo ratón"),
|
||||
("One-Finger Tap", "Toque con un dedo"),
|
||||
("Left Mouse", "Ratón izquierdo"),
|
||||
("One-Long Tap", "Un toque largo"),
|
||||
("Two-Finger Tap", "Toque con dos dedos"),
|
||||
("Right Mouse", "Botón derecho"),
|
||||
("One-Finger Move", "Movimiento con un dedo"),
|
||||
("Double Tap & Move", "Toca dos veces y mueve"),
|
||||
("Mouse Drag", "Arrastre de ratón"),
|
||||
("Three-Finger vertically", "Tres dedos verticalmente"),
|
||||
("Mouse Wheel", "Rueda de ratón"),
|
||||
("Two-Finger Move", "Movimiento con dos dedos"),
|
||||
("Canvas Move", "Movimiento de lienzo"),
|
||||
("Pinch to Zoom", "Pellizcar para ampliar"),
|
||||
("Canvas Zoom", "Ampliar lienzo"),
|
||||
("Reset canvas", "Restablecer lienzo"),
|
||||
("No permission of file transfer", "Sin permiso de transferencia de archivos"),
|
||||
("Note", "Nota"),
|
||||
("Connection", "Conexión"),
|
||||
("Share Screen", "Compartir pantalla"),
|
||||
("CLOSE", "CERRAR"),
|
||||
("OPEN", "ABRIR"),
|
||||
("Chat", "Chat"),
|
||||
("Total", "Total"),
|
||||
("items", "items"),
|
||||
("Selected", "Seleccionado"),
|
||||
("Screen Capture", "Captura de pantalla"),
|
||||
("Input Control", "Control de entrada"),
|
||||
("Audio Capture", "Captura de audio"),
|
||||
("File Connection", "Conexión de archivos"),
|
||||
("Screen Connection", "Conexión de pantalla"),
|
||||
("Do you accept?", "Aceptas?"),
|
||||
("Open System Setting", "Configuración del sistema abierto"),
|
||||
("How to get Android input permission?", "Cómo obtener el permiso de entrada de Android?"),
|
||||
("android_input_permission_tip1", "Para que un dispositivo remoto controle su dispositivo Android a través del mouse o toque, debe permitir que RustDesk use el servicio de \"Accesibilidad\"."),
|
||||
("android_input_permission_tip2", "Vaya a la página de configuración del sistema que se abrirá a continuación, busque y acceda a [Servicios instalados], active el servicio [RustDesk Input]."),
|
||||
("android_new_connection_tip", "Se recibió una nueva solicitud de control para el dispositivo actual."),
|
||||
("android_service_will_start_tip", "Habilitar la captura de pantalla iniciará automáticamente el servicio, lo que permitirá que otros dispositivos soliciten una conexión desde este dispositivo."),
|
||||
("android_stop_service_tip", "Cerrar el servicio cerrará automáticamente todas las conexiones establecidas."),
|
||||
("android_version_audio_tip", "La versión actual de Android no admite la captura de audio, actualice a Android 10 o posterior."),
|
||||
("android_start_service_tip", "Toque el permiso [Iniciar servicio] o ABRIR [Captura de pantalla] para iniciar el servicio de uso compartido de pantalla."),
|
||||
("Account", "Cuenta"),
|
||||
("Overwrite", "Sobrescribir"),
|
||||
("This file exists, skip or overwrite this file?", "Este archivo existe, ¿omitir o sobrescribir este archivo?"),
|
||||
("Quit", "Salir"),
|
||||
("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"),
|
||||
("Help", "Ayuda"),
|
||||
("Failed", "Fallido"),
|
||||
("Succeeded", "Logrado"),
|
||||
("Someone turns on privacy mode, exit", "Alguien active el modo privacidad, salga"),
|
||||
("Unsupported", "No soportado"),
|
||||
("Peer denied", "Par negado"),
|
||||
("Please install plugins", "Instale complementos"),
|
||||
("Peer exit", "Par salio"),
|
||||
("Failed to turn off", "Error al apagar"),
|
||||
("Turned off", "Apagado"),
|
||||
("In privacy mode", "En modo de privacidad"),
|
||||
("Out privacy mode", "Fuera del modo de privacidad"),
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
17
src/main.rs
17
src/main.rs
@ -106,6 +106,7 @@ fn main() {
|
||||
"desktopicon startmenu",
|
||||
"".to_owned(),
|
||||
false,
|
||||
false,
|
||||
));
|
||||
return;
|
||||
} else if args[0] == "--silent-install" {
|
||||
@ -113,11 +114,9 @@ fn main() {
|
||||
"desktopicon startmenu",
|
||||
"".to_owned(),
|
||||
true,
|
||||
args.len() > 1,
|
||||
));
|
||||
return;
|
||||
} else if args[0] == "--extract" {
|
||||
#[cfg(feature = "with_rc")]
|
||||
hbb_common::allow_err!(crate::rc::extract_resources(&args[1]));
|
||||
} else if args[0] == "--check-hwcodec-config" {
|
||||
#[cfg(feature = "hwcodec")]
|
||||
ipc::check_hwcodec_config();
|
||||
@ -209,7 +208,7 @@ fn main() {
|
||||
.about("RustDesk command line tool")
|
||||
.args_from_usage(&args)
|
||||
.get_matches();
|
||||
use hbb_common::{config::LocalConfig, env_logger::*};
|
||||
use hbb_common::env_logger::*;
|
||||
init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
|
||||
if let Some(p) = matches.value_of("port-forward") {
|
||||
let options: Vec<String> = p.split(":").map(|x| x.to_owned()).collect();
|
||||
@ -236,14 +235,6 @@ fn main() {
|
||||
remote_host = options[3].clone();
|
||||
}
|
||||
let key = matches.value_of("key").unwrap_or("").to_owned();
|
||||
let token = LocalConfig::get_option("access_token");
|
||||
cli::start_one_port_forward(
|
||||
options[0].clone(),
|
||||
port,
|
||||
remote_host,
|
||||
remote_port,
|
||||
key,
|
||||
token,
|
||||
);
|
||||
cli::start_one_port_forward(options[0].clone(), port, remote_host, remote_port, key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +436,12 @@ impl Interface for Session {
|
||||
let mut displays = Vec::new();
|
||||
let mut current = pi.current_display as usize;
|
||||
|
||||
if !lc.is_file_transfer {
|
||||
if lc.is_file_transfer {
|
||||
if pi.username.is_empty() {
|
||||
self.msgbox("error", "Error", "No active console user logged on, please connect and logon first.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if pi.displays.is_empty() {
|
||||
self.msgbox("error", "Remote Error", "No Display");
|
||||
}
|
||||
|
||||
@ -698,7 +698,7 @@ pub fn set_share_rdp(enable: bool) {
|
||||
subkey,
|
||||
if enable { "true" } else { "false" }
|
||||
);
|
||||
run_cmds(cmd, false).ok();
|
||||
run_cmds(cmd, false, "share_rdp").ok();
|
||||
}
|
||||
|
||||
pub fn get_active_username() -> String {
|
||||
@ -835,7 +835,7 @@ pub fn check_update_broker_process() -> ResultType<()> {
|
||||
origin_process_exe = origin_process_exe,
|
||||
cur_exe = cur_exe.to_string_lossy().to_string(),
|
||||
);
|
||||
run_cmds(cmds, false)?;
|
||||
run_cmds(cmds, false, "update_broker")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -876,7 +876,7 @@ pub fn update_me() -> ResultType<()> {
|
||||
lic = register_licence(),
|
||||
);
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
run_cmds(cmds, false)?;
|
||||
run_cmds(cmds, false, "update")?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(2000));
|
||||
std::process::Command::new(&exe).arg("--tray").spawn().ok();
|
||||
std::process::Command::new(&exe).spawn().ok();
|
||||
@ -905,7 +905,7 @@ fn get_after_install(exe: &str) -> String {
|
||||
", ext=ext, exe=exe, app_name=app_name)
|
||||
}
|
||||
|
||||
pub fn install_me(options: &str, path: String, silent: bool) -> ResultType<()> {
|
||||
pub fn install_me(options: &str, path: String, silent: bool, debug: bool) -> ResultType<()> {
|
||||
let uninstall_str = get_uninstall();
|
||||
let mut path = path.trim_end_matches('\\').to_owned();
|
||||
let (subkey, _path, start_menu, exe) = get_default_install_info();
|
||||
@ -929,7 +929,7 @@ pub fn install_me(options: &str, path: String, silent: bool) -> ResultType<()> {
|
||||
version_build = versions[2];
|
||||
}
|
||||
|
||||
let tmp_path = "C:\\Windows\\temp";
|
||||
let tmp_path = std::env::temp_dir().to_string_lossy().to_string();
|
||||
let mk_shortcut = write_cmds(
|
||||
format!(
|
||||
"
|
||||
@ -945,6 +945,7 @@ oLink.Save
|
||||
exe = exe,
|
||||
),
|
||||
"vbs",
|
||||
"mk_shortcut",
|
||||
)?
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
@ -966,6 +967,7 @@ oLink.Save
|
||||
exe = exe,
|
||||
),
|
||||
"vbs",
|
||||
"uninstall_shortcut",
|
||||
)?
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
@ -986,6 +988,7 @@ oLink.Save
|
||||
exe = exe,
|
||||
),
|
||||
"vbs",
|
||||
"tray_shortcut",
|
||||
)?
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
@ -1042,7 +1045,7 @@ reg add {subkey} /f /v WindowsInstaller /t REG_DWORD /d 0
|
||||
cscript \"{mk_shortcut}\"
|
||||
cscript \"{uninstall_shortcut}\"
|
||||
cscript \"{tray_shortcut}\"
|
||||
copy /Y \"{tmp_path}\\{app_name} Tray.lnk\" \"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\\"
|
||||
copy /Y \"{tmp_path}\\{app_name} Tray.lnk\" \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\\"
|
||||
{shortcuts}
|
||||
copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\"
|
||||
del /f \"{mk_shortcut}\"
|
||||
@ -1079,7 +1082,7 @@ sc delete {app_name}
|
||||
lic=register_licence(),
|
||||
after_install=get_after_install(&exe),
|
||||
);
|
||||
run_cmds(cmds, false)?;
|
||||
run_cmds(cmds, debug, "install")?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(2000));
|
||||
if !silent {
|
||||
std::process::Command::new(&exe).spawn()?;
|
||||
@ -1091,11 +1094,11 @@ sc delete {app_name}
|
||||
|
||||
pub fn run_after_install() -> ResultType<()> {
|
||||
let (_, _, _, exe) = get_install_info();
|
||||
run_cmds(get_after_install(&exe), true)
|
||||
run_cmds(get_after_install(&exe), true, "after_install")
|
||||
}
|
||||
|
||||
pub fn run_before_uninstall() -> ResultType<()> {
|
||||
run_cmds(get_before_uninstall(), true)
|
||||
run_cmds(get_before_uninstall(), true, "before_install")
|
||||
}
|
||||
|
||||
fn get_before_uninstall() -> String {
|
||||
@ -1126,7 +1129,7 @@ fn get_uninstall() -> String {
|
||||
rd /s /q \"{path}\"
|
||||
rd /s /q \"{start_menu}\"
|
||||
del /f /q \"%PUBLIC%\\Desktop\\{app_name}*\"
|
||||
del /f /q \"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\{app_name} Tray.lnk\"
|
||||
del /f /q \"%PROGRAMDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\{app_name} Tray.lnk\"
|
||||
",
|
||||
before_uninstall=get_before_uninstall(),
|
||||
subkey=subkey,
|
||||
@ -1137,17 +1140,12 @@ fn get_uninstall() -> String {
|
||||
}
|
||||
|
||||
pub fn uninstall_me() -> ResultType<()> {
|
||||
run_cmds(get_uninstall(), true)
|
||||
run_cmds(get_uninstall(), true, "uninstall")
|
||||
}
|
||||
|
||||
fn write_cmds(cmds: String, ext: &str) -> ResultType<std::path::PathBuf> {
|
||||
fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType<std::path::PathBuf> {
|
||||
let mut tmp = std::env::temp_dir();
|
||||
tmp.push(format!(
|
||||
"{}_{:?}.{}",
|
||||
crate::get_app_name(),
|
||||
cmds.as_ptr(),
|
||||
ext
|
||||
));
|
||||
tmp.push(format!("{}_{}.{}", crate::get_app_name(), tip, ext));
|
||||
let mut file = std::fs::File::create(&tmp)?;
|
||||
// in case cmds mixed with \r\n and \n, make sure all ending with \r\n
|
||||
// in some windows, \r\n required for cmd file to run
|
||||
@ -1170,8 +1168,8 @@ fn to_le(v: &mut [u16]) -> &[u8] {
|
||||
unsafe { v.align_to().1 }
|
||||
}
|
||||
|
||||
fn run_cmds(cmds: String, show: bool) -> ResultType<()> {
|
||||
let tmp = write_cmds(cmds, "bat")?;
|
||||
fn run_cmds(cmds: String, show: bool, tip: &str) -> ResultType<()> {
|
||||
let tmp = write_cmds(cmds, "bat", tip)?;
|
||||
let tmp_fn = tmp.to_str().unwrap_or("");
|
||||
let res = runas::Command::new("cmd")
|
||||
.args(&["/C", &tmp_fn])
|
||||
@ -1348,6 +1346,7 @@ oLink.Save
|
||||
id = id,
|
||||
),
|
||||
"vbs",
|
||||
"connect_shortcut",
|
||||
)?
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
|
||||
@ -216,7 +216,7 @@ impl RendezvousMediator {
|
||||
},
|
||||
Some(Err(e)) => bail!("Failed to receive next {}", e), // maybe socks5 tcp disconnected
|
||||
None => {
|
||||
// unreachable!()
|
||||
bail!("Socket receive none. Maybe socks5 server is down.");
|
||||
},
|
||||
}
|
||||
},
|
||||
@ -231,7 +231,7 @@ impl RendezvousMediator {
|
||||
}
|
||||
last_timer = now;
|
||||
let elapsed_resp = last_register_resp.map(|x| x.elapsed().as_millis() as i64).unwrap_or(REG_INTERVAL);
|
||||
let timeout = (last_register_sent.map(|x| x.elapsed().as_millis() as i64).unwrap_or(REG_INTERVAL) - elapsed_resp) > REG_TIMEOUT;
|
||||
let timeout = (elapsed_resp - last_register_sent.map(|x| x.elapsed().as_millis() as i64).unwrap_or(REG_INTERVAL)) > REG_TIMEOUT;
|
||||
if timeout || elapsed_resp >= REG_INTERVAL {
|
||||
allow_err!(rz.register_peer(&mut socket).await);
|
||||
last_register_sent = now;
|
||||
|
||||
@ -3,6 +3,7 @@ use super::{input_service::*, *};
|
||||
use crate::clipboard_file::*;
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
use crate::common::update_clipboard;
|
||||
use crate::video_service;
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel};
|
||||
use crate::{ipc, VERSION};
|
||||
@ -69,7 +70,6 @@ pub struct Connection {
|
||||
audio: bool,
|
||||
file: bool,
|
||||
last_test_delay: i64,
|
||||
image_quality: i32,
|
||||
lock_after_session_end: bool,
|
||||
show_remote_cursor: bool, // by peer
|
||||
ip: String,
|
||||
@ -105,7 +105,7 @@ impl Subscriber for ConnInner {
|
||||
}
|
||||
}
|
||||
|
||||
const TEST_DELAY_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
const TEST_DELAY_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
const SEC30: Duration = Duration::from_secs(30);
|
||||
const H1: Duration = Duration::from_secs(3600);
|
||||
const MILLI1: Duration = Duration::from_millis(1);
|
||||
@ -154,7 +154,6 @@ impl Connection {
|
||||
audio: Config::get_option("enable-audio").is_empty(),
|
||||
file: Config::get_option("enable-file-transfer").is_empty(),
|
||||
last_test_delay: 0,
|
||||
image_quality: ImageQuality::Balanced.value(),
|
||||
lock_after_session_end: false,
|
||||
show_remote_cursor: false,
|
||||
ip: "".to_owned(),
|
||||
@ -376,8 +375,11 @@ impl Connection {
|
||||
if time > 0 && conn.last_test_delay == 0 {
|
||||
conn.last_test_delay = time;
|
||||
let mut msg_out = Message::new();
|
||||
let qos = video_service::VIDEO_QOS.lock().unwrap();
|
||||
msg_out.set_test_delay(TestDelay{
|
||||
time,
|
||||
last_delay:qos.current_delay,
|
||||
target_bitrate:qos.target_bitrate,
|
||||
..Default::default()
|
||||
});
|
||||
conn.inner.send(msg_out.into());
|
||||
@ -394,9 +396,8 @@ impl Connection {
|
||||
let _ = privacy_mode::turn_off_privacy(0);
|
||||
}
|
||||
video_service::notify_video_frame_feched(id, None);
|
||||
video_service::update_test_latency(id, 0);
|
||||
video_service::update_image_quality(id, None);
|
||||
scrap::codec::Encoder::update_video_encoder(id, scrap::codec::EncoderUpdate::Remove);
|
||||
video_service::VIDEO_QOS.lock().unwrap().reset();
|
||||
if let Err(err) = conn.try_port_forward_loop(&mut rx_from_cm).await {
|
||||
conn.on_close(&err.to_string(), false);
|
||||
}
|
||||
@ -665,7 +666,7 @@ impl Connection {
|
||||
res.set_peer_info(pi);
|
||||
} else {
|
||||
try_activate_screen();
|
||||
match super::video_service::get_displays() {
|
||||
match video_service::get_displays() {
|
||||
Err(err) => {
|
||||
res.set_error(format!("X11 error: {}", err));
|
||||
}
|
||||
@ -903,10 +904,11 @@ impl Connection {
|
||||
self.inner.send(msg_out.into());
|
||||
} else {
|
||||
self.last_test_delay = 0;
|
||||
let latency = crate::get_time() - t.time;
|
||||
if latency > 0 {
|
||||
super::video_service::update_test_latency(self.inner.id(), latency);
|
||||
}
|
||||
let new_delay = (crate::get_time() - t.time) as u32;
|
||||
video_service::VIDEO_QOS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.update_network_delay(new_delay);
|
||||
}
|
||||
} else if self.authorized {
|
||||
match msg.union {
|
||||
@ -1082,7 +1084,7 @@ impl Connection {
|
||||
},
|
||||
Some(message::Union::misc(misc)) => match misc.union {
|
||||
Some(misc::Union::switch_display(s)) => {
|
||||
super::video_service::switch_display(s.display);
|
||||
video_service::switch_display(s.display);
|
||||
}
|
||||
Some(misc::Union::chat_message(c)) => {
|
||||
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
|
||||
@ -1092,7 +1094,7 @@ impl Connection {
|
||||
}
|
||||
Some(misc::Union::refresh_video(r)) => {
|
||||
if r {
|
||||
super::video_service::refresh();
|
||||
video_service::refresh();
|
||||
}
|
||||
}
|
||||
Some(misc::Union::video_received(_)) => {
|
||||
@ -1112,13 +1114,18 @@ impl Connection {
|
||||
async fn update_option(&mut self, o: &OptionMessage) {
|
||||
log::info!("Option update: {:?}", o);
|
||||
if let Ok(q) = o.image_quality.enum_value() {
|
||||
self.image_quality = q.value();
|
||||
super::video_service::update_image_quality(self.inner.id(), Some(q.value()));
|
||||
}
|
||||
let q = o.custom_image_quality;
|
||||
if q > 0 {
|
||||
self.image_quality = q;
|
||||
super::video_service::update_image_quality(self.inner.id(), Some(q));
|
||||
let mut image_quality = None;
|
||||
if let ImageQuality::NotSet = q {
|
||||
if o.custom_image_quality > 0 {
|
||||
image_quality = Some(o.custom_image_quality as _);
|
||||
}
|
||||
} else {
|
||||
image_quality = Some(q.value() as _)
|
||||
}
|
||||
video_service::VIDEO_QOS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.update_image_quality(image_quality);
|
||||
}
|
||||
if let Ok(q) = o.lock_after_session_end.enum_value() {
|
||||
if q != BoolOption::NotSet {
|
||||
|
||||
@ -37,19 +37,249 @@ use std::{
|
||||
use virtual_display;
|
||||
|
||||
pub const NAME: &'static str = "video";
|
||||
const FPS: u8 = 30;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref CURRENT_DISPLAY: Arc<Mutex<usize>> = Arc::new(Mutex::new(usize::MAX));
|
||||
static ref LAST_ACTIVE: Arc<Mutex<Instant>> = Arc::new(Mutex::new(Instant::now()));
|
||||
static ref SWITCH: Arc<Mutex<bool>> = Default::default();
|
||||
static ref TEST_LATENCIES: Arc<Mutex<HashMap<i32, i64>>> = Default::default();
|
||||
static ref IMAGE_QUALITIES: Arc<Mutex<HashMap<i32, i32>>> = Default::default();
|
||||
static ref FRAME_FETCHED_NOTIFIER: (UnboundedSender<(i32, Option<Instant>)>, Arc<TokioMutex<UnboundedReceiver<(i32, Option<Instant>)>>>) = {
|
||||
let (tx, rx) = unbounded_channel();
|
||||
(tx, Arc::new(TokioMutex::new(rx)))
|
||||
};
|
||||
static ref PRIVACY_MODE_CONN_ID: Mutex<i32> = Mutex::new(0);
|
||||
static ref IS_CAPTURER_MAGNIFIER_SUPPORTED: bool = is_capturer_mag_supported();
|
||||
pub static ref VIDEO_QOS: Arc<Mutex<VideoQoS>> = Default::default();
|
||||
}
|
||||
|
||||
pub struct VideoQoS {
|
||||
width: u32,
|
||||
height: u32,
|
||||
user_image_quality: u32,
|
||||
current_image_quality: u32,
|
||||
enable_abr: bool,
|
||||
|
||||
pub current_delay: u32,
|
||||
pub fps: u8, // abr
|
||||
pub target_bitrate: u32, // abr
|
||||
updated: bool,
|
||||
|
||||
state: AdaptiveState,
|
||||
last_delay: u32,
|
||||
count: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum AdaptiveState {
|
||||
Normal,
|
||||
LowDelay,
|
||||
HeightDelay,
|
||||
}
|
||||
|
||||
impl Default for VideoQoS {
|
||||
fn default() -> Self {
|
||||
VideoQoS {
|
||||
fps: FPS,
|
||||
user_image_quality: ImageQuality::Balanced.value() as _,
|
||||
current_image_quality: ImageQuality::Balanced.value() as _,
|
||||
enable_abr: false,
|
||||
width: 0,
|
||||
height: 0,
|
||||
current_delay: 0,
|
||||
target_bitrate: 0,
|
||||
updated: false,
|
||||
state: AdaptiveState::Normal,
|
||||
last_delay: 0,
|
||||
count: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const MAX: f32 = 1.2;
|
||||
const MIN: f32 = 0.8;
|
||||
const MAX_COUNT: u32 = 3;
|
||||
const MAX_DELAY: u32 = 500;
|
||||
const MIN_DELAY: u32 = 50;
|
||||
|
||||
impl VideoQoS {
|
||||
pub fn set_size(&mut self, width: u32, height: u32) {
|
||||
if width == 0 || height == 0 {
|
||||
return;
|
||||
}
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
}
|
||||
|
||||
pub fn spf(&mut self) -> Duration {
|
||||
if self.fps <= 0 {
|
||||
self.fps = FPS;
|
||||
}
|
||||
time::Duration::from_secs_f32(1. / (self.fps as f32))
|
||||
}
|
||||
|
||||
// abr
|
||||
pub fn update_network_delay(&mut self, delay: u32) {
|
||||
if self.current_delay.eq(&0) {
|
||||
self.current_delay = delay;
|
||||
return;
|
||||
}
|
||||
let current_delay = self.current_delay as f32;
|
||||
|
||||
self.current_delay = delay / 2 + self.current_delay / 2;
|
||||
log::debug!(
|
||||
"update_network_delay:{}, {}, state:{:?},count:{}",
|
||||
self.current_delay,
|
||||
delay,
|
||||
self.state,
|
||||
self.count
|
||||
);
|
||||
|
||||
if self.current_delay < MIN_DELAY {
|
||||
if self.fps != 30 && self.current_image_quality != self.user_image_quality {
|
||||
log::debug!("current_delay is normal, set to user_image_quality");
|
||||
self.fps = 30;
|
||||
self.current_image_quality = self.user_image_quality;
|
||||
let _ = self.generate_bitrate().ok();
|
||||
self.updated = true;
|
||||
}
|
||||
self.state = AdaptiveState::Normal;
|
||||
} else if self.current_delay > MAX_DELAY {
|
||||
if self.fps != 5 && self.current_image_quality != 25 {
|
||||
log::debug!("current_delay is very height, set fps to 5, image_quality to 25");
|
||||
self.fps = 5;
|
||||
self.current_image_quality = 25;
|
||||
let _ = self.generate_bitrate().ok();
|
||||
self.updated = true;
|
||||
}
|
||||
} else {
|
||||
let delay = delay as f32;
|
||||
let last_delay = self.last_delay as f32;
|
||||
match self.state {
|
||||
AdaptiveState::Normal => {
|
||||
if delay > current_delay * MAX {
|
||||
self.state = AdaptiveState::HeightDelay;
|
||||
} else if delay < current_delay * MIN
|
||||
&& self.current_image_quality < self.user_image_quality
|
||||
{
|
||||
self.state = AdaptiveState::LowDelay;
|
||||
}
|
||||
self.count = 1;
|
||||
self.last_delay = self.current_delay
|
||||
}
|
||||
AdaptiveState::HeightDelay => {
|
||||
if delay > last_delay {
|
||||
if self.count > MAX_COUNT {
|
||||
self.decrease_quality();
|
||||
self.reset_state();
|
||||
return;
|
||||
}
|
||||
self.count += 1;
|
||||
} else {
|
||||
self.reset_state();
|
||||
}
|
||||
}
|
||||
AdaptiveState::LowDelay => {
|
||||
if delay < last_delay * MIN {
|
||||
if self.count > MAX_COUNT {
|
||||
self.increase_quality();
|
||||
self.reset_state();
|
||||
return;
|
||||
}
|
||||
self.count += 1;
|
||||
} else {
|
||||
self.reset_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_state(&mut self) {
|
||||
self.count = 0;
|
||||
self.state = AdaptiveState::Normal;
|
||||
}
|
||||
|
||||
fn increase_quality(&mut self) {
|
||||
log::debug!("Adaptive increase quality");
|
||||
if self.fps < FPS {
|
||||
log::debug!("increase fps {} -> {}", self.fps, FPS);
|
||||
self.fps = FPS;
|
||||
} else {
|
||||
self.current_image_quality += self.current_image_quality / 2;
|
||||
let _ = self.generate_bitrate().ok();
|
||||
log::debug!("increase quality:{}", self.current_image_quality);
|
||||
}
|
||||
self.updated = true;
|
||||
}
|
||||
|
||||
fn decrease_quality(&mut self) {
|
||||
log::debug!("Adaptive decrease quality");
|
||||
if self.fps < 15 {
|
||||
log::debug!("fps is low enough :{}", self.fps);
|
||||
return;
|
||||
}
|
||||
if self.current_image_quality < ImageQuality::Low.value() as _ {
|
||||
self.fps = self.fps / 2;
|
||||
log::debug!("decrease fps:{}", self.fps);
|
||||
} else {
|
||||
self.current_image_quality -= self.current_image_quality / 2;
|
||||
let _ = self.generate_bitrate().ok();
|
||||
log::debug!("decrease quality:{}", self.current_image_quality);
|
||||
};
|
||||
self.updated = true;
|
||||
}
|
||||
|
||||
pub fn update_image_quality(&mut self, image_quality: Option<u32>) {
|
||||
if let Some(image_quality) = image_quality {
|
||||
if image_quality < 10 || image_quality > 200 {
|
||||
self.current_image_quality = ImageQuality::Balanced.value() as _;
|
||||
}
|
||||
if self.current_image_quality != image_quality {
|
||||
self.current_image_quality = image_quality;
|
||||
let _ = self.generate_bitrate().ok();
|
||||
self.updated = true;
|
||||
}
|
||||
} else {
|
||||
self.current_image_quality = ImageQuality::Balanced.value() as _;
|
||||
}
|
||||
self.user_image_quality = self.current_image_quality;
|
||||
}
|
||||
|
||||
pub fn generate_bitrate(&mut self) -> ResultType<u32> {
|
||||
// https://www.nvidia.com/en-us/geforce/guides/broadcasting-guide/
|
||||
if self.width == 0 || self.height == 0 {
|
||||
bail!("Fail to generate_bitrate, width or height is not set");
|
||||
}
|
||||
if self.current_image_quality == 0 {
|
||||
self.current_image_quality = ImageQuality::Balanced.value() as _;
|
||||
}
|
||||
|
||||
let base_bitrate = ((self.width * self.height) / 800) as u32;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
// fix when andorid screen shrinks
|
||||
let fix = Display::fix_quality() as u32;
|
||||
log::debug!("Android screen, fix quality:{}", fix);
|
||||
let base_bitrate = base_bitrate * fix;
|
||||
self.target_bitrate = base_bitrate * self.image_quality / 100;
|
||||
Ok(self.target_bitrate)
|
||||
}
|
||||
self.target_bitrate = base_bitrate * self.current_image_quality / 100;
|
||||
Ok(self.target_bitrate)
|
||||
}
|
||||
|
||||
pub fn check_if_updated(&mut self) -> bool {
|
||||
if self.updated {
|
||||
self.updated = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
*self = Default::default();
|
||||
}
|
||||
}
|
||||
|
||||
fn is_capturer_mag_supported() -> bool {
|
||||
@ -129,7 +359,7 @@ impl VideoFrameController {
|
||||
}
|
||||
|
||||
trait TraitCapturer {
|
||||
fn frame<'a>(&'a mut self, timeout_ms: u32) -> Result<Frame<'a>>;
|
||||
fn frame<'a>(&'a mut self, timeout: Duration) -> Result<Frame<'a>>;
|
||||
|
||||
#[cfg(windows)]
|
||||
fn is_gdi(&self) -> bool;
|
||||
@ -138,8 +368,8 @@ trait TraitCapturer {
|
||||
}
|
||||
|
||||
impl TraitCapturer for Capturer {
|
||||
fn frame<'a>(&'a mut self, timeout_ms: u32) -> Result<Frame<'a>> {
|
||||
self.frame(timeout_ms)
|
||||
fn frame<'a>(&'a mut self, timeout: Duration) -> Result<Frame<'a>> {
|
||||
self.frame(timeout)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@ -155,7 +385,7 @@ impl TraitCapturer for Capturer {
|
||||
|
||||
#[cfg(windows)]
|
||||
impl TraitCapturer for scrap::CapturerMag {
|
||||
fn frame<'a>(&'a mut self, _timeout_ms: u32) -> Result<Frame<'a>> {
|
||||
fn frame<'a>(&'a mut self, _timeout_ms: Duration) -> Result<Frame<'a>> {
|
||||
self.frame(_timeout_ms)
|
||||
}
|
||||
|
||||
@ -326,9 +556,6 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
#[cfg(windows)]
|
||||
ensure_close_virtual_device()?;
|
||||
|
||||
let fps = 30;
|
||||
let wait = 1000 / fps;
|
||||
let spf = time::Duration::from_secs_f32(1. / (fps as f32));
|
||||
let (ndisplay, current, display) = get_current_display()?;
|
||||
let (origin, width, height) = (display.origin(), display.width(), display.height());
|
||||
log::debug!(
|
||||
@ -342,16 +569,21 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
num_cpus::get(),
|
||||
);
|
||||
|
||||
let q = get_image_quality();
|
||||
let (bitrate, rc_min_quantizer, rc_max_quantizer, speed) = get_quality(width, height, q);
|
||||
log::info!("bitrate={}, rc_min_quantizer={}", bitrate, rc_min_quantizer);
|
||||
let mut video_qos = VIDEO_QOS.lock().unwrap();
|
||||
|
||||
video_qos.set_size(width as _, height as _);
|
||||
let mut spf = video_qos.spf();
|
||||
let bitrate = video_qos.generate_bitrate()?;
|
||||
drop(video_qos);
|
||||
|
||||
log::info!("init bitrate={}", bitrate);
|
||||
|
||||
let encoder_cfg = match Encoder::current_hw_encoder_name() {
|
||||
Some(codec_name) => EncoderCfg::HW(HwEncoderConfig {
|
||||
codec_name,
|
||||
width,
|
||||
height,
|
||||
bitrate_ratio: q >> 8,
|
||||
bitrate_ratio: bitrate as _,
|
||||
}),
|
||||
None => EncoderCfg::VPX(VpxEncoderConfig {
|
||||
width: width as _,
|
||||
@ -359,9 +591,6 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
timebase: [1, 1000], // Output timestamp precision
|
||||
bitrate,
|
||||
codec: VpxVideoCodecId::VP9,
|
||||
rc_min_quantizer,
|
||||
rc_max_quantizer,
|
||||
speed,
|
||||
num_threads: (num_cpus::get() / 2) as _,
|
||||
}),
|
||||
};
|
||||
@ -418,10 +647,24 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
let mut try_gdi = 1;
|
||||
#[cfg(windows)]
|
||||
log::info!("gdi: {}", c.is_gdi());
|
||||
|
||||
while sp.ok() {
|
||||
#[cfg(windows)]
|
||||
check_uac_switch(privacy_mode_id, captuerer_privacy_mode_id)?;
|
||||
|
||||
{
|
||||
let mut video_qos = VIDEO_QOS.lock().unwrap();
|
||||
if video_qos.check_if_updated() {
|
||||
log::debug!(
|
||||
"qos is updated, target_bitrate:{}, fps:{}",
|
||||
video_qos.target_bitrate,
|
||||
video_qos.fps
|
||||
);
|
||||
encoder.set_bitrate(video_qos.target_bitrate).unwrap();
|
||||
spf = video_qos.spf();
|
||||
}
|
||||
}
|
||||
|
||||
if *SWITCH.lock().unwrap() {
|
||||
bail!("SWITCH");
|
||||
}
|
||||
@ -430,9 +673,6 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
bail!("SWITCH");
|
||||
}
|
||||
check_privacy_mode_changed(&sp, privacy_mode_id)?;
|
||||
if get_image_quality() != q {
|
||||
bail!("SWITCH");
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if crate::platform::windows::desktop_changed() {
|
||||
@ -454,7 +694,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
frame_controller.reset();
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
let res = match (*c).frame(wait as _) {
|
||||
let res = match c.frame(spf) {
|
||||
Ok(frame) => {
|
||||
let time = now - start;
|
||||
let ms = (time.as_secs() * 1000 + time.subsec_millis() as u64) as i64;
|
||||
@ -477,7 +717,7 @@ fn run(sp: GenericService) -> ResultType<()> {
|
||||
};
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
let res = match (*c).frame(wait as _) {
|
||||
let res = match c.frame(spf) {
|
||||
Ok(frame) => {
|
||||
let time = now - start;
|
||||
let ms = (time.as_secs() * 1000 + time.subsec_millis() as u64) as i64;
|
||||
@ -743,82 +983,3 @@ fn get_current_display() -> ResultType<(usize, usize, Display)> {
|
||||
}
|
||||
return Ok((n, current, displays.remove(current)));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_latency(id: i32, latency: i64, latencies: &mut HashMap<i32, i64>) {
|
||||
if latency <= 0 {
|
||||
latencies.remove(&id);
|
||||
} else {
|
||||
latencies.insert(id, latency);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_test_latency(id: i32, latency: i64) {
|
||||
update_latency(id, latency, &mut *TEST_LATENCIES.lock().unwrap());
|
||||
}
|
||||
|
||||
fn convert_quality(q: i32) -> i32 {
|
||||
let q = {
|
||||
if q == ImageQuality::Balanced.value() {
|
||||
(100 * 2 / 3, 12)
|
||||
} else if q == ImageQuality::Low.value() {
|
||||
(100 / 2, 18)
|
||||
} else if q == ImageQuality::Best.value() {
|
||||
(100, 12)
|
||||
} else {
|
||||
let bitrate = q >> 8 & 0xFF;
|
||||
let quantizer = q & 0xFF;
|
||||
(bitrate * 2, (100 - quantizer) * 36 / 100)
|
||||
}
|
||||
};
|
||||
if q.0 <= 0 {
|
||||
0
|
||||
} else {
|
||||
q.0 << 8 | q.1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_image_quality(id: i32, q: Option<i32>) {
|
||||
match q {
|
||||
Some(q) => {
|
||||
let q = convert_quality(q);
|
||||
if q > 0 {
|
||||
IMAGE_QUALITIES.lock().unwrap().insert(id, q);
|
||||
} else {
|
||||
IMAGE_QUALITIES.lock().unwrap().remove(&id);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
IMAGE_QUALITIES.lock().unwrap().remove(&id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_image_quality() -> i32 {
|
||||
IMAGE_QUALITIES
|
||||
.lock()
|
||||
.unwrap()
|
||||
.values()
|
||||
.min()
|
||||
.unwrap_or(&convert_quality(ImageQuality::Balanced.value()))
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_quality(w: usize, h: usize, q: i32) -> (u32, u32, u32, i32) {
|
||||
// https://www.nvidia.com/en-us/geforce/guides/broadcasting-guide/
|
||||
let bitrate = q >> 8 & 0xFF;
|
||||
let quantizer = q & 0xFF;
|
||||
let b = ((w * h) / 1000) as u32;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
// fix when andorid screen shrinks
|
||||
let fix = Display::fix_quality() as u32;
|
||||
log::debug!("Android screen, fix quality:{}", fix);
|
||||
let b = b * fix;
|
||||
return (bitrate as u32 * b / 100, quantizer as _, 56, 7);
|
||||
}
|
||||
|
||||
(bitrate as u32 * b / 100, quantizer as _, 56, 7)
|
||||
}
|
||||
|
||||
@ -213,7 +213,9 @@ impl UI {
|
||||
fn install_me(&mut self, _options: String, _path: String) {
|
||||
#[cfg(windows)]
|
||||
std::thread::spawn(move || {
|
||||
allow_err!(crate::platform::windows::install_me(&_options, _path, false));
|
||||
allow_err!(crate::platform::windows::install_me(
|
||||
&_options, _path, false, false
|
||||
));
|
||||
std::process::exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
@ -159,6 +159,7 @@ class Header: Reactor.Component {
|
||||
<li #custom type="image-quality"><span>{svg_checkmark}</span>{translate('Custom')}</li>
|
||||
<div .separator />
|
||||
<li #show-remote-cursor .toggle-option><span>{svg_checkmark}</span>{translate('Show remote cursor')}</li>
|
||||
<li #show-quality-monitor .toggle-option><span>{svg_checkmark}</span>{translate('Show quality monitor')}</li>
|
||||
{audio_enabled ? <li #disable-audio .toggle-option><span>{svg_checkmark}</span>{translate('Mute')}</li> : ""}
|
||||
{is_win && pi.platform == 'Windows' && file_enabled ? <li #enable-file-transfer .toggle-option><span>{svg_checkmark}</span>{translate('Allow file copy and paste')}</li> : ""}
|
||||
{keyboard_enabled && clipboard_enabled ? <li #disable-clipboard .toggle-option><span>{svg_checkmark}</span>{translate('Disable clipboard')}</li> : ""}
|
||||
@ -315,7 +316,9 @@ class Header: Reactor.Component {
|
||||
handle_custom_image_quality();
|
||||
} else if (me.id == "privacy-mode") {
|
||||
togglePrivacyMode(me.id);
|
||||
} else if (me.attributes.hasClass("toggle-option")) {
|
||||
} else if (me.id == "show-quality-monitor") {
|
||||
toggleQualityMonitor(me.id);
|
||||
}else if (me.attributes.hasClass("toggle-option")) {
|
||||
handler.toggle_option(me.id);
|
||||
toggleMenuState();
|
||||
} else if (!me.attributes.hasClass("selected")) {
|
||||
@ -332,16 +335,13 @@ class Header: Reactor.Component {
|
||||
}
|
||||
|
||||
function handle_custom_image_quality() {
|
||||
var tmp = handler.get_custom_image_quality();
|
||||
var bitrate0 = tmp[0] || 50;
|
||||
var quantizer0 = tmp.length > 1 ? tmp[1] : 100;
|
||||
var bitrate = handler.get_custom_image_quality()[0] / 2;
|
||||
msgbox("custom", "Custom Image Quality", "<div .form> \
|
||||
<div><input type=\"hslider\" style=\"width: 50%\" name=\"bitrate\" max=\"100\" min=\"10\" value=\"" + bitrate0 + "\"/ buddy=\"bitrate-buddy\"><b #bitrate-buddy>x</b>% bitrate</div> \
|
||||
<div><input type=\"hslider\" style=\"width: 50%\" name=\"quantizer\" max=\"100\" min=\"0\" value=\"" + quantizer0 + "\"/ buddy=\"quantizer-buddy\"><b #quantizer-buddy>x</b>% quantizer</div> \
|
||||
<div><input type=\"hslider\" style=\"width: 50%\" name=\"bitrate\" max=\"100\" min=\"10\" value=\"" + bitrate + "\"/ buddy=\"bitrate-buddy\"><b #bitrate-buddy>x</b>% Bitrate</div> \
|
||||
</div>", function(res=null) {
|
||||
if (!res) return;
|
||||
if (!res.bitrate) return;
|
||||
handler.save_custom_image_quality(res.bitrate, res.quantizer);
|
||||
handler.save_custom_image_quality(res.bitrate * 2);
|
||||
toggleMenuState();
|
||||
});
|
||||
}
|
||||
@ -357,7 +357,7 @@ function toggleMenuState() {
|
||||
for (var el in $$(menu#display-options>li)) {
|
||||
el.attributes.toggleClass("selected", values.indexOf(el.id) >= 0);
|
||||
}
|
||||
for (var id in ["show-remote-cursor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) {
|
||||
for (var id in ["show-remote-cursor", "show-quality-monitor", "disable-audio", "enable-file-transfer", "disable-clipboard", "lock-after-session-end"]) {
|
||||
var el = self.select('#' + id);
|
||||
if (el) {
|
||||
var value = handler.get_toggle_option(id);
|
||||
@ -425,6 +425,17 @@ function togglePrivacyMode(privacy_id) {
|
||||
}
|
||||
}
|
||||
|
||||
function toggleQualityMonitor(name) {
|
||||
var show = handler.get_toggle_option(name);
|
||||
if (show) {
|
||||
$(#quality-monitor).style.set{ display: "none" };
|
||||
} else {
|
||||
$(#quality-monitor).style.set{ display: "block" };
|
||||
}
|
||||
handler.toggle_option(name);
|
||||
toggleMenuState();
|
||||
}
|
||||
|
||||
handler.updateBlockInputState = function(input_blocked) {
|
||||
if (!input_blocked) {
|
||||
handler.toggle_option("block-input");
|
||||
|
||||
@ -9,6 +9,16 @@ div#video-wrapper {
|
||||
background: #212121;
|
||||
}
|
||||
|
||||
div#quality-monitor {
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: #7571719c;
|
||||
padding: 5px;
|
||||
min-width: 150px;
|
||||
color: azure;
|
||||
border: solid azure;
|
||||
}
|
||||
|
||||
video#handler {
|
||||
behavior: native-remote video;
|
||||
size: *;
|
||||
@ -24,7 +34,7 @@ img#cursor {
|
||||
}
|
||||
|
||||
.goup {
|
||||
transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
table#remote-folder-view {
|
||||
@ -33,4 +43,4 @@ table#remote-folder-view {
|
||||
|
||||
table#local-folder-view {
|
||||
context-menu: selector(menu#local-folder-view);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
<html window-resizable window-frame="extended">
|
||||
<head>
|
||||
<style>
|
||||
@import url(common.css);
|
||||
@import url(remote.css);
|
||||
@import url(file_transfer.css);
|
||||
@import url(header.css);
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
|
||||
<head>
|
||||
<style>
|
||||
@import url(common.css);
|
||||
@import url(remote.css);
|
||||
@import url(file_transfer.css);
|
||||
@import url(header.css);
|
||||
</style>
|
||||
<script type="text/tiscript">
|
||||
include "common.tis";
|
||||
include "msgbox.tis";
|
||||
include "remote.tis";
|
||||
@ -15,23 +16,28 @@
|
||||
include "grid.tis";
|
||||
include "header.tis";
|
||||
</script>
|
||||
</head>
|
||||
<header>
|
||||
<div.window-icon role="window-icon"><icon /></div>
|
||||
</head>
|
||||
<header>
|
||||
<div.window-icon role="window-icon">
|
||||
<icon />
|
||||
</div>
|
||||
<caption role="window-caption" />
|
||||
<div.window-toolbar />
|
||||
<div.window-buttons />
|
||||
</header>
|
||||
<body>
|
||||
<div #video-wrapper>
|
||||
<video #handler>
|
||||
<div style="position: relative">
|
||||
<img #cursor src="in-memory:cursor" />
|
||||
</div>
|
||||
</video>
|
||||
</div>
|
||||
<div #file-transfer-wrapper>
|
||||
</div>
|
||||
<div #msgbox />
|
||||
</body>
|
||||
</html>
|
||||
</header>
|
||||
|
||||
<body>
|
||||
<div #video-wrapper>
|
||||
<video #handler>
|
||||
<div #quality-monitor style="position: absolute; display: none" />
|
||||
<div style="position: relative">
|
||||
<img #cursor src="in-memory:cursor" />
|
||||
</div>
|
||||
</video>
|
||||
</div>
|
||||
<div #file-transfer-wrapper>
|
||||
</div>
|
||||
<div #msgbox />
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -2,7 +2,7 @@ use std::{
|
||||
collections::HashMap,
|
||||
ops::Deref,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
Arc, Mutex, RwLock,
|
||||
},
|
||||
};
|
||||
@ -223,7 +223,7 @@ impl sciter::EventHandler for Handler {
|
||||
fn get_custom_image_quality();
|
||||
fn save_view_style(String);
|
||||
fn save_image_quality(String);
|
||||
fn save_custom_image_quality(i32, i32);
|
||||
fn save_custom_image_quality(i32);
|
||||
fn refresh_video();
|
||||
fn get_toggle_option(String);
|
||||
fn is_privacy_mode_supported();
|
||||
@ -234,6 +234,25 @@ impl sciter::EventHandler for Handler {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct QualityStatus {
|
||||
speed: String,
|
||||
fps: i32,
|
||||
delay: i32,
|
||||
target_bitrate: i32,
|
||||
}
|
||||
|
||||
impl Default for QualityStatus {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
speed: Default::default(),
|
||||
fps: -1,
|
||||
delay: -1,
|
||||
target_bitrate: -1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub fn new(cmd: String, id: String, args: Vec<String>) -> Self {
|
||||
let me = Self {
|
||||
@ -249,6 +268,18 @@ impl Handler {
|
||||
me
|
||||
}
|
||||
|
||||
fn update_quality_status(&self, status: QualityStatus) {
|
||||
self.call2(
|
||||
"updateQualityStatus",
|
||||
&make_args!(
|
||||
status.speed,
|
||||
status.fps,
|
||||
status.delay,
|
||||
status.target_bitrate
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
fn start_keyboard_hook(&self) {
|
||||
if self.is_port_forward() || self.is_file_transfer() {
|
||||
return;
|
||||
@ -533,12 +564,12 @@ impl Handler {
|
||||
self.send(Data::Message(LoginConfigHandler::refresh()));
|
||||
}
|
||||
|
||||
fn save_custom_image_quality(&mut self, bitrate: i32, quantizer: i32) {
|
||||
fn save_custom_image_quality(&mut self, custom_image_quality: i32) {
|
||||
let msg = self
|
||||
.lc
|
||||
.write()
|
||||
.unwrap()
|
||||
.save_custom_image_quality(bitrate, quantizer);
|
||||
.save_custom_image_quality(custom_image_quality);
|
||||
self.send(Data::Message(msg));
|
||||
}
|
||||
|
||||
@ -1296,7 +1327,10 @@ async fn io_loop(handler: Handler) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
let (video_sender, audio_sender) = start_video_audio_threads(|data: &[u8]| {
|
||||
let frame_count = Arc::new(AtomicUsize::new(0));
|
||||
let frame_count_cl = frame_count.clone();
|
||||
let (video_sender, audio_sender) = start_video_audio_threads(move |data: &[u8]| {
|
||||
frame_count_cl.fetch_add(1, Ordering::Relaxed);
|
||||
VIDEO
|
||||
.lock()
|
||||
.unwrap()
|
||||
@ -1319,6 +1353,8 @@ async fn io_loop(handler: Handler) {
|
||||
first_frame: false,
|
||||
#[cfg(windows)]
|
||||
clipboard_file_context: None,
|
||||
data_count: Arc::new(AtomicUsize::new(0)),
|
||||
frame_count,
|
||||
};
|
||||
remote.io_loop(&key, &token).await;
|
||||
remote.sync_jobs_status_to_local().await;
|
||||
@ -1369,6 +1405,8 @@ struct Remote {
|
||||
first_frame: bool,
|
||||
#[cfg(windows)]
|
||||
clipboard_file_context: Option<Box<CliprdrClientContext>>,
|
||||
data_count: Arc<AtomicUsize>,
|
||||
frame_count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
impl Remote {
|
||||
@ -1394,6 +1432,8 @@ impl Remote {
|
||||
#[cfg(windows)]
|
||||
let mut rx_clip_client = get_rx_clip_client().lock().await;
|
||||
|
||||
let mut status_timer = time::interval(Duration::new(1, 0));
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
res = peer.next() => {
|
||||
@ -1406,6 +1446,7 @@ impl Remote {
|
||||
}
|
||||
Ok(ref bytes) => {
|
||||
last_recv_time = Instant::now();
|
||||
self.data_count.fetch_add(bytes.len(), Ordering::Relaxed);
|
||||
if !self.handle_msg_from_peer(bytes, &mut peer).await {
|
||||
break
|
||||
}
|
||||
@ -1450,6 +1491,16 @@ impl Remote {
|
||||
self.timer = time::interval_at(Instant::now() + SEC30, SEC30);
|
||||
}
|
||||
}
|
||||
_ = status_timer.tick() => {
|
||||
let speed = self.data_count.swap(0, Ordering::Relaxed);
|
||||
let speed = format!("{:.2}kB/s", speed as f32 / 1024 as f32);
|
||||
let fps = self.frame_count.swap(0, Ordering::Relaxed) as _;
|
||||
self.handler.update_quality_status(QualityStatus {
|
||||
speed,
|
||||
fps,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
log::debug!("Exit io_loop of id={}", self.handler.id);
|
||||
@ -2370,7 +2421,7 @@ impl Remote {
|
||||
}
|
||||
back_notification::PrivacyModeState::OffSucceeded => {
|
||||
self.handler
|
||||
.msgbox("custom-nocancel", "Privacy mode", "Out privacy mode");
|
||||
.msgbox("custom-nocancel", "Privacy mode", "Out privacy mode");
|
||||
self.update_privacy_mode(false);
|
||||
}
|
||||
back_notification::PrivacyModeState::OffByPeer => {
|
||||
@ -2549,7 +2600,16 @@ impl Interface for Handler {
|
||||
}
|
||||
|
||||
async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream) {
|
||||
handle_test_delay(t, peer).await;
|
||||
if !t.from_client {
|
||||
self.update_quality_status(QualityStatus {
|
||||
delay: t.last_delay as _,
|
||||
target_bitrate: t.target_bitrate as _,
|
||||
..Default::default()
|
||||
});
|
||||
let mut msg_out = Message::new();
|
||||
msg_out.set_test_delay(t);
|
||||
allow_err!(peer.send(&msg_out).await);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -456,6 +456,45 @@ function self.closing() {
|
||||
if (is_file_transfer || is_port_forward || size_adapted) handler.save_size(x, y, w, h);
|
||||
}
|
||||
|
||||
var qualityMonitor;
|
||||
var qualityMonitorData = [];
|
||||
|
||||
class QualityMonitor: Reactor.Component
|
||||
{
|
||||
function this() {
|
||||
qualityMonitor = this;
|
||||
if (handler.get_toggle_option("show-quality-monitor")) {
|
||||
$(#quality-monitor).style.set{ display: "block" };
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
return <div >
|
||||
<div>
|
||||
Speed: {qualityMonitorData[0]}
|
||||
</div>
|
||||
<div>
|
||||
FPS: {qualityMonitorData[1]}
|
||||
</div>
|
||||
<div>
|
||||
Delay: {qualityMonitorData[2]} ms
|
||||
</div>
|
||||
<div>
|
||||
Target Bitrate: {qualityMonitorData[3]}kb
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
$(#quality-monitor).content(<QualityMonitor />);
|
||||
handler.updateQualityStatus = function(speed, fps, delay, bitrate) {
|
||||
speed ? qualityMonitorData[0] = speed:null;
|
||||
fps > -1 ? qualityMonitorData[1] = fps:null;
|
||||
delay > -1 ? qualityMonitorData[2] = delay:null;
|
||||
bitrate > -1 ? qualityMonitorData[3] = bitrate:null;
|
||||
qualityMonitor.update();
|
||||
}
|
||||
|
||||
handler.setPermission = function(name, enabled) {
|
||||
self.timer(60ms, function() {
|
||||
if (name == "keyboard") keyboard_enabled = enabled;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user