mirror of https://github.com/wayvr-org/wayvr.git
Merge branch 'main' into wgui_named_colors
This commit is contained in:
commit
d6268c0c20
|
|
@ -362,13 +362,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-native-tls"
|
||||
version = "0.5.0"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9343dc5acf07e79ff82d0c37899f079db3534d99f189a1837c8e549c99405bec"
|
||||
checksum = "37dd6b179962fe4048a6f81d4c0d7ed419a21fdf49204b4c6b04971693358e79"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"native-tls",
|
||||
"thiserror 1.0.69",
|
||||
"thiserror 2.0.18",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
|
@ -623,7 +623,7 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -911,7 +911,7 @@ dependencies = [
|
|||
"num-traits",
|
||||
"pure-rust-locales",
|
||||
"wasm-bindgen",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1211,7 +1211,7 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"windows 0.62.2",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1415,7 +1415,6 @@ dependencies = [
|
|||
"chrono",
|
||||
"glam",
|
||||
"http-body-util",
|
||||
"hyper",
|
||||
"keyvalues-parser",
|
||||
"log",
|
||||
"lz4_flex",
|
||||
|
|
@ -1425,6 +1424,7 @@ dependencies = [
|
|||
"smol",
|
||||
"smol-hyper",
|
||||
"strum",
|
||||
"ureq",
|
||||
"uuid",
|
||||
"wayvr-ipc",
|
||||
"wgui",
|
||||
|
|
@ -2089,7 +2089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8"
|
||||
dependencies = [
|
||||
"rustix 1.1.4",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2176,25 +2176,6 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b40ca9252762c466af32d0b1002e91e4e1bc5398f77455e55474deb466355ff5"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"http",
|
||||
"indexmap 2.14.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.7.1"
|
||||
|
|
@ -2360,19 +2341,10 @@ version = "1.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2387,7 +2359,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.62.2",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2662,10 +2634,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "069323743400cb7ab06a8fe5c1ed911d36b6919ec531661d034c89083629595b"
|
||||
dependencies = [
|
||||
"doctest-file",
|
||||
"futures-core",
|
||||
"libc",
|
||||
"recvmsg",
|
||||
"tokio",
|
||||
"widestring",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
|
@ -2773,7 +2743,7 @@ dependencies = [
|
|||
"simd_cesu8",
|
||||
"thiserror 2.0.18",
|
||||
"walkdir",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2929,7 +2899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2939,7 +2909,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3071,9 +3041,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.18.0"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9"
|
||||
checksum = "0b6180140927ee907000b0aa540091f6ea512ead4447c92b8fc35bc72788a5a6"
|
||||
dependencies = [
|
||||
"hashbrown 0.17.1",
|
||||
]
|
||||
|
|
@ -3175,17 +3145,6 @@ version = "0.5.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moveit"
|
||||
version = "0.6.0"
|
||||
|
|
@ -3654,6 +3613,17 @@ dependencies = [
|
|||
"objc2-foundation 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-open-directory"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb82bed227edf5201dfedf072bba4015a33d3d4a98519837295a90f0a23f676d"
|
||||
dependencies = [
|
||||
"objc2 0.6.4",
|
||||
"objc2-core-foundation",
|
||||
"objc2-foundation 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-quartz-core"
|
||||
version = "0.2.2"
|
||||
|
|
@ -3927,7 +3897,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall 0.5.18",
|
||||
"smallvec",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4715,6 +4685,20 @@ dependencies = [
|
|||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.17",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rodio"
|
||||
version = "0.22.2"
|
||||
|
|
@ -4876,6 +4860,41 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
|
||||
dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
|
|
@ -5130,9 +5149,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.18"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
|
||||
checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
|
|
@ -5403,16 +5422,6 @@ version = "0.3.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
|
|
@ -5461,6 +5470,12 @@ dependencies = [
|
|||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "svgtypes"
|
||||
version = "0.16.1"
|
||||
|
|
@ -5575,16 +5590,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.37.2"
|
||||
version = "0.39.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f"
|
||||
checksum = "d2071df9448915b71c4fe6d25deaf1c22f12bd234f01540b77312bb8e41361e6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"objc2-core-foundation",
|
||||
"objc2-io-kit",
|
||||
"windows 0.61.3",
|
||||
"objc2-open-directory",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5810,37 +5826,7 @@ version = "1.52.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5956,12 +5942,6 @@ dependencies = [
|
|||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.25.1"
|
||||
|
|
@ -6005,6 +5985,7 @@ dependencies = [
|
|||
"log",
|
||||
"rust-embed",
|
||||
"tracing-subscriber",
|
||||
"ureq",
|
||||
"vulkano",
|
||||
"vulkano-shaders",
|
||||
"wgui",
|
||||
|
|
@ -6060,6 +6041,41 @@ version = "0.2.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"flate2",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"ureq-proto",
|
||||
"utf8-zero",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.8"
|
||||
|
|
@ -6094,6 +6110,12 @@ dependencies = [
|
|||
"xmlwriter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-zero"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e"
|
||||
|
||||
[[package]]
|
||||
name = "utf8_iter"
|
||||
version = "1.0.4"
|
||||
|
|
@ -6228,15 +6250,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||
dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
|
|
@ -6538,14 +6551,15 @@ name = "wayvr-ipc"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel",
|
||||
"async-io",
|
||||
"bytes",
|
||||
"interprocess",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"smol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6559,7 +6573,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"shell-words",
|
||||
"tokio",
|
||||
"smol",
|
||||
"wayvr-ipc",
|
||||
]
|
||||
|
||||
|
|
@ -6583,6 +6597,15 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.12"
|
||||
|
|
@ -6679,38 +6702,16 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||
dependencies = [
|
||||
"windows-collections 0.2.0",
|
||||
"windows-core 0.61.2",
|
||||
"windows-future 0.2.1",
|
||||
"windows-link 0.1.3",
|
||||
"windows-numerics 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections 0.3.2",
|
||||
"windows-core 0.62.2",
|
||||
"windows-future 0.3.2",
|
||||
"windows-numerics 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6719,20 +6720,7 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6743,20 +6731,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
|||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
"windows-threading 0.1.0",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6765,9 +6742,9 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
"windows-threading 0.2.1",
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6792,45 +6769,20 @@ dependencies = [
|
|||
"syn 2.0.118",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||
dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6839,16 +6791,7 @@ version = "0.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6857,7 +6800,7 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6893,7 +6836,7 @@ version = "0.61.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -6927,22 +6870,13 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -7363,6 +7297,12 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
version = "0.2.4"
|
||||
|
|
|
|||
|
|
@ -14,12 +14,17 @@ members = [
|
|||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0.100"
|
||||
async-channel = "2.3"
|
||||
async-io = "2.1"
|
||||
bytes = { version = "1.11.1" }
|
||||
chrono = "0.4.42"
|
||||
clap = { version = "4.5.53", features = ["derive"] }
|
||||
dbus = { version = "0.9.12" }
|
||||
glam = { version = "0.30.9", features = ["mint", "serde"] }
|
||||
idmap = "0.2.2"
|
||||
idmap-derive = "0.2.22"
|
||||
interprocess = { version = "2.2.3" }
|
||||
libc = "0.2.178"
|
||||
log = "0.4.29"
|
||||
pipewire = { version = "0.10", features = ["v0_3_33", "v0_3_65"] }
|
||||
regex = "1.12.2"
|
||||
|
|
@ -31,6 +36,7 @@ slotmap = "1.1.1"
|
|||
smallvec = "1.15.2"
|
||||
smol = "2.0.2"
|
||||
strum = { version = "0.27.2", features = ["derive"] }
|
||||
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
||||
uuid = { version = "1.19.0", features = ["fast-rng", "serde", "v4"] }
|
||||
vulkano = {
|
||||
version = "0.35.2",
|
||||
|
|
@ -43,6 +49,7 @@ vulkano-shaders = "0.35.0"
|
|||
wayland-client = { version = "0.31" }
|
||||
wayland-protocols = { version = "0.32" }
|
||||
wayland-protocols-misc = { version = "0.3.12" }
|
||||
winit = "0.30.12"
|
||||
xdg = "3.0.0"
|
||||
|
||||
[patch.crates-io]
|
||||
|
|
|
|||
|
|
@ -8,27 +8,32 @@ authors = ["galister", "oo8dev"]
|
|||
repository = "https://github.com/wlx-team/wayvr"
|
||||
|
||||
[dependencies]
|
||||
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
|
||||
wgui = { path = "../wgui/" }
|
||||
wlx-common = { path = "../wlx-common" }
|
||||
|
||||
anyhow.workspace = true
|
||||
async-native-tls = "0.5.0"
|
||||
chrono = "0.4.42"
|
||||
chrono.workspace = true
|
||||
glam = { workspace = true, features = ["mint", "serde"] }
|
||||
http-body-util = "0.1.3"
|
||||
hyper = { version = "1.8.1", features = ["client", "http1", "http2"] }
|
||||
keyvalues-parser = { git = "https://codeberg.org/CosmicHarper/vdf-rs.git", rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145" }
|
||||
log.workspace = true
|
||||
lz4_flex = { version = "0.13.1", features = ["frame"] }
|
||||
rust-embed.workspace = true
|
||||
serde = { workspace = true, features = ["rc"] }
|
||||
serde_json.workspace = true
|
||||
smol = { workspace = true }
|
||||
smol-hyper = "0.1.1"
|
||||
strum.workspace = true
|
||||
uuid.workspace = true
|
||||
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
|
||||
wgui = { path = "../wgui/" }
|
||||
wlx-common = { path = "../wlx-common" }
|
||||
xdg.workspace = true
|
||||
|
||||
async-native-tls = "0.6.0"
|
||||
http-body-util = "0.1.3"
|
||||
keyvalues-parser = {
|
||||
git = "https://codeberg.org/CosmicHarper/vdf-rs.git",
|
||||
rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145"
|
||||
}
|
||||
lz4_flex = { version = "0.13.1", features = ["frame"] }
|
||||
smol-hyper = "0.1.1"
|
||||
ureq = "3.3.0"
|
||||
|
||||
[features]
|
||||
default = ["monado"]
|
||||
monado = []
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use crate::util::{networking::http_client, steam_utils::AppID};
|
||||
use anyhow::Context;
|
||||
use serde::Deserialize;
|
||||
use wlx_common::{async_executor::AsyncExecutor, cache_dir};
|
||||
use wlx_common::cache_dir;
|
||||
|
||||
pub struct CoverArt {
|
||||
// can be empty in case if data couldn't be fetched (use a fallback image then)
|
||||
pub compressed_image_data: Vec<u8>,
|
||||
}
|
||||
|
||||
pub async fn request_image(executor: AsyncExecutor, app_id: AppID) -> anyhow::Result<CoverArt> {
|
||||
pub async fn request_image(app_id: AppID) -> anyhow::Result<CoverArt> {
|
||||
let cache_file_path = format!("cover_arts/{}.bin", app_id);
|
||||
|
||||
// check if file already exists in cache directory
|
||||
|
|
@ -23,7 +23,7 @@ pub async fn request_image(executor: AsyncExecutor, app_id: AppID) -> anyhow::Re
|
|||
app_id
|
||||
);
|
||||
|
||||
match http_client::get_simple(&executor, &url).await {
|
||||
match http_client::get_simple(&url).await {
|
||||
Ok(response) => {
|
||||
log::info!("Success");
|
||||
cache_dir::set_data(&cache_file_path, &response.data).await?;
|
||||
|
|
@ -55,11 +55,7 @@ pub struct AppDetailsJSONData {
|
|||
pub developers: Vec<String>, // ["Valve"]
|
||||
}
|
||||
|
||||
async fn get_app_details_json_internal(
|
||||
executor: AsyncExecutor,
|
||||
cache_file_path: &str,
|
||||
app_id: AppID,
|
||||
) -> anyhow::Result<AppDetailsJSONData> {
|
||||
async fn get_app_details_json_internal(cache_file_path: &str, app_id: AppID) -> anyhow::Result<AppDetailsJSONData> {
|
||||
// check if file already exists in cache directory
|
||||
if let Some(data) = cache_dir::get_data(cache_file_path).await {
|
||||
return Ok(serde_json::from_value(serde_json::from_slice(&data)?)?);
|
||||
|
|
@ -68,7 +64,7 @@ async fn get_app_details_json_internal(
|
|||
// Fetch from Steam API
|
||||
log::info!("Fetching app detail ID {}", app_id);
|
||||
let url = format!("https://store.steampowered.com/api/appdetails?appids={}", app_id);
|
||||
let response = http_client::get_simple(&executor, &url).await?;
|
||||
let response = http_client::get_simple(&url).await?;
|
||||
let res_utf8 = String::from_utf8(response.data)?;
|
||||
let root = serde_json::from_str::<serde_json::Value>(&res_utf8)?;
|
||||
let body = root.get(&app_id).context("invalid body")?;
|
||||
|
|
@ -88,10 +84,10 @@ async fn get_app_details_json_internal(
|
|||
Ok(app_details)
|
||||
}
|
||||
|
||||
pub async fn get_app_details_json(executor: AsyncExecutor, app_id: AppID) -> Option<AppDetailsJSONData> {
|
||||
pub async fn get_app_details_json(app_id: AppID) -> Option<AppDetailsJSONData> {
|
||||
let cache_file_path = format!("app_details/{}.json", app_id);
|
||||
|
||||
match get_app_details_json_internal(executor, &cache_file_path, app_id).await {
|
||||
match get_app_details_json_internal(&cache_file_path, app_id).await {
|
||||
Ok(r) => Some(r),
|
||||
Err(e) => {
|
||||
log::error!("Failed to get app details: {:?}", e);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,15 @@
|
|||
//
|
||||
// example smol+hyper usage derived from
|
||||
// https://github.com/smol-rs/smol/blob/master/examples/hyper-client.rs
|
||||
// under Apache-2.0 + MIT license.
|
||||
// Repository URL: https://github.com/smol-rs/smol
|
||||
//
|
||||
|
||||
use anyhow::Context as _;
|
||||
use async_native_tls::TlsStream;
|
||||
use http_body_util::{BodyStream, Empty};
|
||||
use hyper::Request;
|
||||
use smol::{net::TcpStream, prelude::*};
|
||||
use std::convert::TryInto;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use wlx_common::async_executor::AsyncExecutor;
|
||||
use smol::{
|
||||
Task,
|
||||
channel::{Receiver, bounded},
|
||||
io::AsyncWriteExt as _,
|
||||
};
|
||||
use std::{io::Read as _, path::Path, str, sync::OnceLock};
|
||||
|
||||
const IO_BUFFER_SIZE: usize = 256 * 1024;
|
||||
const CHANNEL_CAPACITY: usize = 4;
|
||||
const MAX_INITIAL_ALLOCATION: usize = 8 * 1024 * 1024;
|
||||
|
||||
pub struct HttpClientResponse {
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
|
@ -21,276 +17,224 @@ pub struct HttpClientResponse {
|
|||
impl HttpClientResponse {
|
||||
pub fn into_json<T>(self) -> anyhow::Result<T>
|
||||
where
|
||||
T: for<'a> serde::Deserialize<'a>,
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
let utf8 = str::from_utf8(&self.data)?;
|
||||
Ok(serde_json::from_str::<T>(utf8)?)
|
||||
Ok(serde_json::from_str(utf8)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ProgressFuncData {
|
||||
pub bytes_downloaded: u64,
|
||||
pub file_size: u64,
|
||||
}
|
||||
|
||||
pub type ProgressFunc = Box<dyn Fn(ProgressFuncData)>;
|
||||
pub type ProgressFunc<'a> = Box<dyn FnMut(ProgressFuncData) + 'a>;
|
||||
|
||||
pub struct GetParams<'a> {
|
||||
pub executor: &'a AsyncExecutor,
|
||||
pub url: &'a str,
|
||||
pub on_progress: Option<ProgressFunc>,
|
||||
pub on_progress: Option<ProgressFunc<'a>>,
|
||||
}
|
||||
|
||||
pub async fn get(params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> {
|
||||
let url: hyper::Uri = params.url.try_into()?;
|
||||
let req = Request::builder()
|
||||
.header(
|
||||
hyper::header::HOST,
|
||||
url.authority().context("invalid authority")?.clone().as_str(),
|
||||
)
|
||||
.uri(url)
|
||||
.body(Empty::new())?;
|
||||
|
||||
let resp = fetch_and_follow_redirects(params.executor, req, params.on_progress, ¶ms.url).await?;
|
||||
|
||||
Ok(resp)
|
||||
struct DownloadStream {
|
||||
file_size: u64,
|
||||
chunks: Receiver<Vec<u8>>,
|
||||
worker: Task<anyhow::Result<()>>,
|
||||
}
|
||||
|
||||
async fn fetch_and_follow_redirects(
|
||||
executor: &AsyncExecutor,
|
||||
req: hyper::Request<Empty<&'static [u8]>>,
|
||||
mut on_progress: Option<ProgressFunc>,
|
||||
initial_url: &str,
|
||||
) -> anyhow::Result<HttpClientResponse> {
|
||||
log::info!("fetching URL \"{}\"", initial_url);
|
||||
static HTTP_AGENT: OnceLock<ureq::Agent> = OnceLock::new();
|
||||
|
||||
let resp = fetch(executor, req.clone()).await?;
|
||||
let status = resp.status();
|
||||
fn http_agent() -> &'static ureq::Agent {
|
||||
HTTP_AGENT.get_or_init(|| {
|
||||
ureq::Agent::config_builder()
|
||||
.max_redirects(10)
|
||||
.http_status_as_error(false)
|
||||
.build()
|
||||
.new_agent()
|
||||
})
|
||||
}
|
||||
|
||||
if status.is_redirection() {
|
||||
let next_req = follow_single_redirect(&req, &resp).await?;
|
||||
/// Starts a blocking HTTP request and streams its body through a bounded
|
||||
/// asynchronous channel.
|
||||
///
|
||||
/// The request, TLS operations, and all BodyReader reads remain inside one
|
||||
/// blocking worker. Only owned byte chunks cross back to the async task.
|
||||
async fn start_download(url: &str, allow_missing_content_length: bool) -> anyhow::Result<DownloadStream> {
|
||||
let url = url.to_owned();
|
||||
let agent = http_agent().clone();
|
||||
|
||||
let max_redirects = 10;
|
||||
let mut current_req = next_req;
|
||||
let mut redirects = 0;
|
||||
loop {
|
||||
let resp = fetch(executor, current_req.clone()).await?;
|
||||
let resp_status = resp.status();
|
||||
let (metadata_tx, metadata_rx) = bounded::<u64>(1);
|
||||
|
||||
if resp_status.is_success() {
|
||||
let (parts, body) = resp.into_parts();
|
||||
let (chunk_tx, chunk_rx) = bounded::<Vec<u8>>(CHANNEL_CAPACITY);
|
||||
|
||||
let mut bytes_downloaded: u64 = 0;
|
||||
let mut file_size: u64 = 1;
|
||||
let worker = smol::unblock(move || -> anyhow::Result<()> {
|
||||
log::info!("fetching URL \"{}\"", url);
|
||||
|
||||
if let Some(val) = parts.headers.get("Content-Length")
|
||||
&& let Ok(str) = val.to_str()
|
||||
&& let Ok(s) = str.parse()
|
||||
{
|
||||
file_size = s;
|
||||
}
|
||||
let response = agent
|
||||
.get(&url)
|
||||
.header("Accept-Encoding", "identity")
|
||||
.call()
|
||||
.with_context(|| format!("failed to fetch URL \"{url}\""))?;
|
||||
|
||||
let data = BodyStream::new(body)
|
||||
.try_fold(Vec::new(), |mut body, chunk| {
|
||||
if let Some(chunk) = chunk.data_ref() {
|
||||
bytes_downloaded += chunk.len() as u64;
|
||||
body.extend_from_slice(chunk);
|
||||
if !response.status().is_success() {
|
||||
anyhow::bail!("non-200 HTTP response: {}", response.status().as_u16(),);
|
||||
}
|
||||
|
||||
if let Some(on_progress) = &mut on_progress {
|
||||
on_progress(ProgressFuncData {
|
||||
bytes_downloaded,
|
||||
file_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
Ok(body)
|
||||
})
|
||||
.await?;
|
||||
let file_size = match response.body().content_length() {
|
||||
Some(file_size) => file_size,
|
||||
|
||||
return Ok(HttpClientResponse { data });
|
||||
} else if resp_status.is_redirection() {
|
||||
redirects += 1;
|
||||
if redirects >= max_redirects {
|
||||
anyhow::bail!("too many redirects");
|
||||
}
|
||||
current_req = follow_single_redirect(¤t_req, &resp).await?;
|
||||
} else {
|
||||
anyhow::bail!("non-200 HTTP response: {}", resp_status.as_str());
|
||||
None if allow_missing_content_length => 0,
|
||||
|
||||
None => {
|
||||
anyhow::bail!("HTTP response has no Content-Length header");
|
||||
}
|
||||
};
|
||||
|
||||
if metadata_tx.send_blocking(file_size).is_err() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
drop(metadata_tx);
|
||||
|
||||
let mut reader = response.into_body().into_reader();
|
||||
let mut buffer = [0_u8; IO_BUFFER_SIZE];
|
||||
|
||||
loop {
|
||||
let count = reader.read(&mut buffer).with_context(|| {
|
||||
format!(
|
||||
"failed while reading HTTP response body \
|
||||
from \"{url}\""
|
||||
)
|
||||
})?;
|
||||
|
||||
if count == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
let chunk = buffer[..count].to_vec();
|
||||
|
||||
if chunk_tx.send_blocking(chunk).is_err() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
let file_size = match metadata_rx.recv().await {
|
||||
Ok(file_size) => file_size,
|
||||
|
||||
Err(_) => {
|
||||
worker.await?;
|
||||
|
||||
anyhow::bail!("HTTP worker stopped before providing response metadata");
|
||||
}
|
||||
};
|
||||
|
||||
Ok(DownloadStream {
|
||||
file_size,
|
||||
chunks: chunk_rx,
|
||||
worker,
|
||||
})
|
||||
}
|
||||
|
||||
/// Downloads a response into memory.
|
||||
///
|
||||
/// This fails if the server does not provide a Content-Length header.
|
||||
pub async fn get(mut params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> {
|
||||
let DownloadStream {
|
||||
file_size,
|
||||
chunks,
|
||||
worker,
|
||||
} = start_download(params.url, false).await?;
|
||||
|
||||
let initial_capacity = usize::try_from(file_size).unwrap_or(0).min(MAX_INITIAL_ALLOCATION);
|
||||
|
||||
let mut data = Vec::with_capacity(initial_capacity);
|
||||
let mut bytes_downloaded = 0_u64;
|
||||
|
||||
while let Ok(chunk) = chunks.recv().await {
|
||||
bytes_downloaded += chunk.len() as u64;
|
||||
data.extend_from_slice(&chunk);
|
||||
|
||||
if let Some(on_progress) = params.on_progress.as_mut() {
|
||||
on_progress(ProgressFuncData {
|
||||
bytes_downloaded,
|
||||
file_size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if !resp.status().is_success() {
|
||||
// non-200 HTTP response
|
||||
anyhow::bail!("non-200 HTTP response: {}", resp.status().as_str());
|
||||
worker.await?;
|
||||
|
||||
if bytes_downloaded != file_size {
|
||||
anyhow::bail!(
|
||||
"HTTP response size mismatch: expected {} bytes, received {}",
|
||||
file_size,
|
||||
bytes_downloaded,
|
||||
);
|
||||
}
|
||||
|
||||
let mut bytes_downloaded: u64 = 0;
|
||||
let mut file_size: u64 = 1;
|
||||
|
||||
let (parts, body) = resp.into_parts();
|
||||
|
||||
// that's a pretty interesting way to get file size :]
|
||||
if let Some(val) = parts.headers.get("Content-Length")
|
||||
&& let Ok(str) = val.to_str()
|
||||
&& let Ok(s) = str.parse()
|
||||
{
|
||||
file_size = s;
|
||||
}
|
||||
|
||||
let data = BodyStream::new(body)
|
||||
.try_fold(Vec::new(), |mut body, chunk| {
|
||||
if let Some(chunk) = chunk.data_ref() {
|
||||
bytes_downloaded += chunk.len() as u64;
|
||||
body.extend_from_slice(chunk);
|
||||
|
||||
if let Some(on_progress) = &mut on_progress {
|
||||
on_progress(ProgressFuncData {
|
||||
bytes_downloaded,
|
||||
file_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
Ok(body)
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(HttpClientResponse { data })
|
||||
}
|
||||
|
||||
fn uri_try_from_str(s: &str) -> anyhow::Result<hyper::http::uri::PathAndQuery> {
|
||||
use std::convert::TryInto;
|
||||
let uri: hyper::Uri = s.try_into().context("invalid URI")?;
|
||||
uri
|
||||
.path_and_query()
|
||||
.ok_or_else(|| anyhow::anyhow!("URI has no path and query component"))
|
||||
.cloned()
|
||||
}
|
||||
/// Downloads a response directly to a file.
|
||||
///
|
||||
/// Unlike `get`, this permits responses without a Content-Length header. In
|
||||
/// that case, `ProgressFuncData::file_size` is zero.
|
||||
///
|
||||
/// An existing file is truncated. If the download fails after the file is
|
||||
/// created, a partial file may remain at `path`.
|
||||
pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef<Path>) -> anyhow::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
|
||||
async fn follow_single_redirect(
|
||||
req: &hyper::Request<Empty<&'static [u8]>>,
|
||||
resp: &hyper::Response<hyper::body::Incoming>,
|
||||
) -> anyhow::Result<hyper::Request<Empty<&'static [u8]>>> {
|
||||
let location = resp
|
||||
.headers()
|
||||
.get(hyper::header::LOCATION)
|
||||
.ok_or_else(|| anyhow::anyhow!("redirect response has no Location header"))?;
|
||||
let DownloadStream {
|
||||
file_size,
|
||||
chunks,
|
||||
worker,
|
||||
} = start_download(params.url, true).await?;
|
||||
|
||||
let location_str = location.to_str().context("invalid redirect location header")?;
|
||||
let mut file = smol::fs::File::create(&path)
|
||||
.await
|
||||
.with_context(|| format!("failed to create download file {:?}", path,))?;
|
||||
|
||||
// resolve relative urls against the original url.
|
||||
let original_uri = req.uri().clone();
|
||||
let next_url: hyper::Uri = if location_str.starts_with("http://") || location_str.starts_with("https://") {
|
||||
hyper::Uri::try_from(location_str).context("invalid redirect location")?
|
||||
} else {
|
||||
let mut parts = original_uri.into_parts();
|
||||
parts.path_and_query = uri_try_from_str(location_str)
|
||||
.context("invalid redirect location")?
|
||||
.into();
|
||||
hyper::Uri::from_parts(parts).context("failed to construct redirect URI")?
|
||||
};
|
||||
let mut bytes_downloaded = 0_u64;
|
||||
|
||||
log::info!("redirecting to \"{}\"", next_url);
|
||||
while let Ok(chunk) = chunks.recv().await {
|
||||
file
|
||||
.write_all(&chunk)
|
||||
.await
|
||||
.with_context(|| format!("failed to write download file {:?}", path,))?;
|
||||
|
||||
let next_req = Request::builder()
|
||||
.header(
|
||||
hyper::header::HOST,
|
||||
next_url.authority().context("invalid authority")?.as_str(),
|
||||
)
|
||||
.uri(next_url)
|
||||
.body(Empty::new())?;
|
||||
bytes_downloaded += chunk.len() as u64;
|
||||
|
||||
Ok(next_req)
|
||||
}
|
||||
|
||||
pub async fn get_simple(executor: &AsyncExecutor, url: &str) -> anyhow::Result<HttpClientResponse> {
|
||||
get(GetParams {
|
||||
executor,
|
||||
url,
|
||||
on_progress: None,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn fetch(
|
||||
ex: &AsyncExecutor,
|
||||
req: hyper::Request<http_body_util::Empty<&'static [u8]>>,
|
||||
) -> anyhow::Result<hyper::Response<hyper::body::Incoming>> {
|
||||
let io = {
|
||||
let host = req.uri().host().context("cannot parse host")?;
|
||||
|
||||
match req.uri().scheme_str() {
|
||||
Some("http") => {
|
||||
let stream = {
|
||||
let port = req.uri().port_u16().unwrap_or(80);
|
||||
smol::net::TcpStream::connect((host, port)).await?
|
||||
};
|
||||
SmolStream::Plain(stream)
|
||||
}
|
||||
Some("https") => {
|
||||
// In case of HTTPS, establish a secure TLS connection first.
|
||||
let stream = {
|
||||
let port = req.uri().port_u16().unwrap_or(443);
|
||||
smol::net::TcpStream::connect((host, port)).await?
|
||||
};
|
||||
let stream = async_native_tls::connect(host, stream).await?;
|
||||
SmolStream::Tls(stream)
|
||||
}
|
||||
scheme => anyhow::bail!("unsupported scheme: {:?}", scheme),
|
||||
}
|
||||
};
|
||||
|
||||
// Spawn the HTTP/1 connection.
|
||||
let (mut sender, conn) = hyper::client::conn::http1::handshake(smol_hyper::rt::FuturesIo::new(io)).await?;
|
||||
ex.spawn(async move {
|
||||
if let Err(e) = conn.await {
|
||||
println!("Connection failed: {:?}", e);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
// Get the result
|
||||
let result = sender.send_request(req).await?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// A TCP or TCP+TLS connection.
|
||||
enum SmolStream {
|
||||
/// A plain TCP connection.
|
||||
Plain(TcpStream),
|
||||
|
||||
/// A TCP connection secured by TLS.
|
||||
Tls(TlsStream<TcpStream>),
|
||||
}
|
||||
|
||||
impl AsyncRead for SmolStream {
|
||||
fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<smol::io::Result<usize>> {
|
||||
match &mut *self {
|
||||
SmolStream::Plain(stream) => Pin::new(stream).poll_read(cx, buf),
|
||||
SmolStream::Tls(stream) => Pin::new(stream).poll_read(cx, buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncWrite for SmolStream {
|
||||
fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<smol::io::Result<usize>> {
|
||||
match &mut *self {
|
||||
SmolStream::Plain(stream) => Pin::new(stream).poll_write(cx, buf),
|
||||
SmolStream::Tls(stream) => Pin::new(stream).poll_write(cx, buf),
|
||||
if let Some(on_progress) = params.on_progress.as_mut() {
|
||||
on_progress(ProgressFuncData {
|
||||
bytes_downloaded,
|
||||
file_size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<smol::io::Result<()>> {
|
||||
match &mut *self {
|
||||
SmolStream::Plain(stream) => Pin::new(stream).poll_close(cx),
|
||||
SmolStream::Tls(stream) => Pin::new(stream).poll_close(cx),
|
||||
}
|
||||
worker.await?;
|
||||
|
||||
file
|
||||
.flush()
|
||||
.await
|
||||
.with_context(|| format!("failed to flush download file {:?}", path,))?;
|
||||
|
||||
if file_size != 0 && bytes_downloaded != file_size {
|
||||
anyhow::bail!(
|
||||
"HTTP response size mismatch: expected {} bytes, received {}",
|
||||
file_size,
|
||||
bytes_downloaded,
|
||||
);
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<smol::io::Result<()>> {
|
||||
match &mut *self {
|
||||
SmolStream::Plain(stream) => Pin::new(stream).poll_flush(cx),
|
||||
SmolStream::Tls(stream) => Pin::new(stream).poll_flush(cx),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_simple(url: &str) -> anyhow::Result<HttpClientResponse> {
|
||||
get(GetParams { url, on_progress: None }).await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,11 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use wgui::{globals::WguiGlobals, renderer_vk::text::custom_glyph::CustomGlyphData};
|
||||
use wlx_common::async_executor::AsyncExecutor;
|
||||
|
||||
use crate::util::networking::http_client;
|
||||
|
||||
pub async fn fetch_to_glyph_data(
|
||||
globals: &WguiGlobals,
|
||||
executor: &AsyncExecutor,
|
||||
url: &str,
|
||||
) -> anyhow::Result<(CustomGlyphData, Rc<Vec<u8>>)> {
|
||||
let res = http_client::get_simple(executor, url).await?;
|
||||
pub async fn fetch_to_glyph_data(globals: &WguiGlobals, url: &str) -> anyhow::Result<(CustomGlyphData, Rc<Vec<u8>>)> {
|
||||
let res = http_client::get_simple(url).await?;
|
||||
let glyph_data = CustomGlyphData::from_bytes_raster(globals, url, &res.data)?;
|
||||
Ok((glyph_data, Rc::new(res.data)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::util::networking::{self, WAYVR_SKYMAPS_ROOT, http_client};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use wlx_common::{async_executor::AsyncExecutor, config_io};
|
||||
use wlx_common::config_io;
|
||||
pub type SkymapUuid = uuid::Uuid;
|
||||
|
||||
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
|
||||
|
|
@ -160,10 +160,10 @@ impl SkymapCatalog {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn request_catalog(executor: &AsyncExecutor) -> anyhow::Result<SkymapCatalog> {
|
||||
pub async fn request_catalog() -> anyhow::Result<SkymapCatalog> {
|
||||
log::info!("Fetching skymap list");
|
||||
|
||||
let res = http_client::get_simple(executor, &format!("{}/catalog.json", networking::WAYVR_SKYMAPS_ROOT)).await?;
|
||||
let res = http_client::get_simple(&format!("{}/catalog.json", networking::WAYVR_SKYMAPS_ROOT)).await?;
|
||||
let catalog = res.into_json::<SkymapCatalog>()?;
|
||||
catalog.validate()?;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,13 +69,7 @@ impl ViewTrait for View {
|
|||
if let Some(on_downloaded) = self.on_downloaded.take() {
|
||||
self
|
||||
.executor
|
||||
.spawn(View::download(
|
||||
self.tasks.clone(),
|
||||
self.executor.clone(),
|
||||
url,
|
||||
path,
|
||||
on_downloaded,
|
||||
))
|
||||
.spawn(View::download(self.tasks.clone(), url, path, on_downloaded))
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
|
@ -189,37 +183,12 @@ impl View {
|
|||
|
||||
async fn download(
|
||||
tasks: Tasks<Task>,
|
||||
executor: AsyncExecutor,
|
||||
url: String,
|
||||
target_path: PathBuf,
|
||||
on_downloaded: Box<dyn FnOnce()>,
|
||||
) -> Option<()> {
|
||||
tasks.push(Task::SetStatusText(String::from("Connecting to the server...")));
|
||||
|
||||
// start downloading from the server with progress reporting
|
||||
let res = handle_async_result(
|
||||
"Download failed",
|
||||
&tasks,
|
||||
http_client::get(http_client::GetParams {
|
||||
executor: &executor,
|
||||
url: &url,
|
||||
on_progress: Some(Box::new({
|
||||
let tasks = tasks.clone();
|
||||
move |data: ProgressFuncData| {
|
||||
tasks.push(Task::SetStatusText(format!(
|
||||
"{}/{} KiB ({}%)",
|
||||
data.bytes_downloaded / 1024,
|
||||
data.file_size / 1024,
|
||||
(data.bytes_downloaded as f32 / data.file_size as f32 * 100.0).round()
|
||||
)))
|
||||
}
|
||||
})),
|
||||
})
|
||||
.await,
|
||||
)?;
|
||||
|
||||
tasks.push(Task::SetStatusText(String::from("Writing to file...")));
|
||||
|
||||
// create parent directory if it doesn't exist yet
|
||||
if let Some(parent) = target_path.parent() {
|
||||
handle_async_result(
|
||||
|
|
@ -229,10 +198,28 @@ impl View {
|
|||
)?;
|
||||
}
|
||||
|
||||
// start downloading from the server with progress reporting
|
||||
handle_async_result(
|
||||
"File write failed",
|
||||
"Download failed",
|
||||
&tasks,
|
||||
smol::fs::write(target_path, res.data).await,
|
||||
http_client::download_to_file(
|
||||
http_client::GetParams {
|
||||
url: &url,
|
||||
on_progress: Some(Box::new({
|
||||
let tasks = tasks.clone();
|
||||
move |data: ProgressFuncData| {
|
||||
tasks.push(Task::SetStatusText(format!(
|
||||
"{}/{} MiB ({}%)",
|
||||
data.bytes_downloaded / 1024 / 1024,
|
||||
data.file_size / 1024 / 1024,
|
||||
(data.bytes_downloaded as f32 / data.file_size as f32 * 100.0).round()
|
||||
)))
|
||||
}
|
||||
})),
|
||||
},
|
||||
&target_path,
|
||||
)
|
||||
.await,
|
||||
)?;
|
||||
|
||||
tasks.push(Task::SetStatusText(String::from("Download finished")));
|
||||
|
|
|
|||
|
|
@ -61,12 +61,8 @@ const GAME_COVER_SIZE_X: f32 = 140.0;
|
|||
const GAME_COVER_SIZE_Y: f32 = 210.0;
|
||||
|
||||
impl View {
|
||||
async fn request_cover_image(
|
||||
executor: AsyncExecutor,
|
||||
manifest: steam_utils::AppManifest,
|
||||
on_loaded: Box<dyn FnOnce(CoverArt)>,
|
||||
) {
|
||||
let cover_art = match cached_fetcher::request_image(executor, manifest.app_id.clone()).await {
|
||||
async fn request_cover_image(manifest: steam_utils::AppManifest, on_loaded: Box<dyn FnOnce(CoverArt)>) {
|
||||
let cover_art = match cached_fetcher::request_image(manifest.app_id.clone()).await {
|
||||
Ok(cover_art) => cover_art,
|
||||
Err(e) => {
|
||||
log::error!("request_cover_image failed: {:?}", e);
|
||||
|
|
@ -286,7 +282,6 @@ impl View {
|
|||
params
|
||||
.executor
|
||||
.spawn(View::request_cover_image(
|
||||
params.executor.clone(),
|
||||
params.manifest.clone(),
|
||||
Box::new(params.on_loaded),
|
||||
))
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ impl ViewTrait for View {
|
|||
}
|
||||
|
||||
impl View {
|
||||
async fn fetch_details(executor: AsyncExecutor, tasks: Tasks<Task>, app_id: AppID) {
|
||||
let Some(details) = cached_fetcher::get_app_details_json(executor, app_id).await else {
|
||||
async fn fetch_details(tasks: Tasks<Task>, app_id: AppID) {
|
||||
let Some(details) = cached_fetcher::get_app_details_json(app_id).await else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ impl View {
|
|||
let tasks = Tasks::new();
|
||||
|
||||
// fetch details from the web
|
||||
let fut = View::fetch_details(params.executor.clone(), tasks.clone(), params.manifest.app_id.clone());
|
||||
let fut = View::fetch_details(tasks.clone(), params.manifest.app_id.clone());
|
||||
params.executor.spawn(fut).detach();
|
||||
|
||||
let id_cover_art_parent = state.get_widget_id("cover_art_parent")?;
|
||||
|
|
|
|||
|
|
@ -119,8 +119,8 @@ impl ViewTrait for View {
|
|||
}
|
||||
|
||||
impl View {
|
||||
async fn skymap_catalog_request_wrapper(tasks: Tasks<Task>, executor: AsyncExecutor) {
|
||||
let res = networking::skymap_catalog::request_catalog(&executor).await;
|
||||
async fn skymap_catalog_request_wrapper(tasks: Tasks<Task>) {
|
||||
let res = networking::skymap_catalog::request_catalog().await;
|
||||
tasks.push(Task::SetSkymapCatalog(Rc::new(res)))
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ impl View {
|
|||
with_text: true,
|
||||
})?;
|
||||
let tasks = Tasks::<Task>::new();
|
||||
let fut = View::skymap_catalog_request_wrapper(tasks.clone(), par.executor.clone());
|
||||
let fut = View::skymap_catalog_request_wrapper(tasks.clone());
|
||||
par.executor.spawn(fut).detach();
|
||||
Ok(Self {
|
||||
id_parent: par.parent_id,
|
||||
|
|
@ -147,15 +147,10 @@ impl View {
|
|||
})
|
||||
}
|
||||
|
||||
async fn request_skymap_preview(
|
||||
globals: WguiGlobals,
|
||||
executor: AsyncExecutor,
|
||||
entry: SkymapCatalogEntry,
|
||||
tasks: Tasks<Task>,
|
||||
) {
|
||||
async fn request_skymap_preview(globals: WguiGlobals, entry: SkymapCatalogEntry, tasks: Tasks<Task>) {
|
||||
tasks.push(Task::SetSkymapPreview((
|
||||
entry.uuid,
|
||||
networking::image_fetch::fetch_to_glyph_data(&globals, &executor, &entry.files.get_url_preview())
|
||||
networking::image_fetch::fetch_to_glyph_data(&globals, &entry.files.get_url_preview())
|
||||
.await
|
||||
.ok(),
|
||||
)));
|
||||
|
|
@ -192,12 +187,7 @@ impl View {
|
|||
let id_list = parser_state.fetch_widget(&layout.state, "list")?.id;
|
||||
|
||||
for entry in &catalog.entries {
|
||||
let task = View::request_skymap_preview(
|
||||
self.globals.clone(),
|
||||
self.executor.clone(),
|
||||
entry.clone(),
|
||||
self.tasks.clone(),
|
||||
);
|
||||
let task = View::request_skymap_preview(self.globals.clone(), entry.clone(), self.tasks.clone());
|
||||
|
||||
let skymap_uuid = entry.uuid;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,14 +8,16 @@ authors = ["galister", "oo8dev"]
|
|||
repository = "https://github.com/wlx-team/wayvr"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
glam = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rust-embed = "8.9.0"
|
||||
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
||||
wgui = { path = "../wgui/" }
|
||||
winit = "0.30.12"
|
||||
vulkano = { workspace = true }
|
||||
vulkano-shaders = { workspace = true }
|
||||
dash-frontend = { path = "../dash-frontend/" }
|
||||
wgui = { path = "../wgui/" }
|
||||
wlx-common = { path = "../wlx-common" }
|
||||
|
||||
anyhow.workspace = true
|
||||
glam.workspace = true
|
||||
log.workspace = true
|
||||
rust-embed.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
vulkano.workspace = true
|
||||
vulkano-shaders.workspace = true
|
||||
winit.workspace = true
|
||||
ureq = "3.3.0"
|
||||
|
|
|
|||
|
|
@ -8,18 +8,19 @@ authors = ["galister", "oo8dev"]
|
|||
repository = "https://github.com/wlx-team/wayvr"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.93"
|
||||
anyhow.workspace = true
|
||||
async-channel.workspace = true
|
||||
async-io.workspace = true
|
||||
bytes.workspace = true
|
||||
log = "0.4.22"
|
||||
interprocess.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
smallvec = "1.13.2"
|
||||
smallvec.workspace = true
|
||||
|
||||
# client-only deps
|
||||
interprocess = { version = "2.2.2", features = ["tokio"], optional = true }
|
||||
serde_json.workspace = true
|
||||
tokio = { version = "1.43.1", features = ["macros"], optional = true }
|
||||
tokio-util = { version = "0.7.13", optional = true }
|
||||
smol = { workspace = true, optional = true }
|
||||
|
||||
[features]
|
||||
default = ["client"]
|
||||
client = ["dep:interprocess", "dep:tokio", "dep:tokio-util"]
|
||||
client = ["dep:smol"]
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
use bytes::BufMut;
|
||||
use interprocess::local_socket::{
|
||||
self, GenericNamespaced,
|
||||
tokio::{Stream, prelude::*},
|
||||
};
|
||||
use interprocess::local_socket::{self, ToNsName};
|
||||
use serde::Serialize;
|
||||
use smallvec::SmallVec;
|
||||
use smol::io::AsyncReadExt;
|
||||
use smol::io::AsyncWriteExt;
|
||||
use smol::lock::Mutex;
|
||||
use std::os::unix::net::UnixStream as StdUnixStream;
|
||||
use std::sync::{Arc, Weak};
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
sync::Mutex,
|
||||
};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::{
|
||||
gen_id,
|
||||
|
|
@ -43,10 +39,10 @@ type SignalFunc = Box<dyn FnMut(&packet_server::PacketServer) -> bool + Send>;
|
|||
pub struct WayVRClient {
|
||||
receiver: ReceiverMutex,
|
||||
sender: SenderMutex,
|
||||
cancel_token: CancellationToken,
|
||||
cancel_tx: async_channel::Sender<()>,
|
||||
exiting: bool,
|
||||
queued_packets: QueuedPacketVec,
|
||||
pub auth: Option<AuthInfo>, // Some if authenticated
|
||||
pub auth: Option<AuthInfo>,
|
||||
pub on_signal: Option<SignalFunc>,
|
||||
}
|
||||
|
||||
|
|
@ -67,8 +63,26 @@ pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()
|
|||
pub type WayVRClientMutex = Arc<Mutex<WayVRClient>>;
|
||||
pub type WayVRClientWeak = Weak<Mutex<WayVRClient>>;
|
||||
|
||||
type ReceiverMutex = Arc<Mutex<local_socket::tokio::RecvHalf>>;
|
||||
type SenderMutex = Arc<Mutex<local_socket::tokio::SendHalf>>;
|
||||
type ReceiverMutex = Arc<Mutex<smol::net::unix::UnixStream>>;
|
||||
type SenderMutex = Arc<Mutex<smol::net::unix::UnixStream>>;
|
||||
|
||||
fn interprocess_stream_to_async(
|
||||
stream: local_socket::Stream,
|
||||
) -> anyhow::Result<smol::net::unix::UnixStream> {
|
||||
use std::os::unix::io::OwnedFd;
|
||||
|
||||
let uds_stream: interprocess::os::unix::uds_local_socket::Stream = match stream {
|
||||
local_socket::Stream::UdSocket(s) => s,
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => anyhow::bail!("Unsupported socket type"),
|
||||
};
|
||||
|
||||
let owned_fd: OwnedFd = uds_stream.into();
|
||||
let std_stream = StdUnixStream::from(owned_fd);
|
||||
|
||||
smol::net::unix::UnixStream::try_from(std_stream)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to wrap socket for async I/O: {}", e))
|
||||
}
|
||||
|
||||
async fn client_runner(client: WayVRClientMutex) -> anyhow::Result<()> {
|
||||
loop {
|
||||
|
|
@ -79,7 +93,7 @@ async fn client_runner(client: WayVRClientMutex) -> anyhow::Result<()> {
|
|||
type Payload = SmallVec<[u8; 64]>;
|
||||
|
||||
async fn read_payload(
|
||||
conn: &mut local_socket::tokio::RecvHalf,
|
||||
conn: &mut smol::net::unix::UnixStream,
|
||||
size: u32,
|
||||
) -> anyhow::Result<Payload> {
|
||||
let mut payload = Payload::new();
|
||||
|
|
@ -122,32 +136,32 @@ impl WayVRClient {
|
|||
|
||||
pub async fn new(client_name: &str) -> anyhow::Result<WayVRClientMutex> {
|
||||
let printname = "/tmp/wayvr_ipc.sock";
|
||||
let name = printname.to_ns_name::<GenericNamespaced>()?;
|
||||
|
||||
let stream = match Stream::connect(name).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
anyhow::bail!("Failed to connect to the WayVR IPC: {}", e)
|
||||
}
|
||||
};
|
||||
let (receiver, sender) = stream.split();
|
||||
let name = printname
|
||||
.to_ns_name::<local_socket::GenericNamespaced>()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to create socket name: {}", e))?;
|
||||
let opts = local_socket::ConnectOptions::new().name(name);
|
||||
let ip_stream = opts
|
||||
.connect_sync()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to connect to the WayVR IPC: {}", e))?;
|
||||
|
||||
let receiver = Arc::new(Mutex::new(receiver));
|
||||
let sender = Arc::new(Mutex::new(sender));
|
||||
let async_stream = interprocess_stream_to_async(ip_stream)?;
|
||||
let receiver = Arc::new(Mutex::new(async_stream.clone()));
|
||||
let sender = Arc::new(Mutex::new(async_stream));
|
||||
|
||||
let cancel_token = CancellationToken::new();
|
||||
let (cancel_tx, cancel_rx) = async_channel::bounded(1);
|
||||
|
||||
let client = Arc::new(Mutex::new(Self {
|
||||
receiver,
|
||||
sender: sender.clone(),
|
||||
cancel_tx,
|
||||
exiting: false,
|
||||
cancel_token: cancel_token.clone(),
|
||||
queued_packets: QueuedPacketVec::new(),
|
||||
auth: None,
|
||||
on_signal: None,
|
||||
}));
|
||||
|
||||
WayVRClient::start_runner(client.clone(), cancel_token);
|
||||
WayVRClient::start_runner(client.clone(), cancel_rx);
|
||||
|
||||
// Send handshake to the server
|
||||
send_packet(
|
||||
|
|
@ -163,17 +177,31 @@ impl WayVRClient {
|
|||
Ok(client)
|
||||
}
|
||||
|
||||
fn start_runner(client: WayVRClientMutex, cancel_token: CancellationToken) {
|
||||
tokio::spawn(async move {
|
||||
tokio::select! {
|
||||
_ = cancel_token.cancelled() => {
|
||||
log::info!("Exiting IPC runner gracefully");
|
||||
}
|
||||
e = client_runner(client.clone()) => {
|
||||
log::info!("IPC Runner failed: {:?}", e);
|
||||
fn start_runner(client: WayVRClientMutex, cancel_rx: async_channel::Receiver<()>) {
|
||||
smol::spawn(async move {
|
||||
let cancel_fut = async {
|
||||
cancel_rx
|
||||
.recv()
|
||||
.await
|
||||
.map_err(|_| anyhow::anyhow!("cancelled"))
|
||||
};
|
||||
|
||||
let result = smol::future::race(client_runner(client.clone()), cancel_fut).await;
|
||||
|
||||
match result {
|
||||
Ok(()) => {
|
||||
log::info!("IPC Runner completed");
|
||||
}
|
||||
Err(e) => {
|
||||
if e.to_string() == "cancelled" {
|
||||
log::info!("Exiting IPC runner gracefully");
|
||||
} else {
|
||||
log::info!("IPC Runner failed: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
async fn tick(client_mtx: WayVRClientMutex) -> anyhow::Result<()> {
|
||||
|
|
@ -185,7 +213,9 @@ impl WayVRClient {
|
|||
// read packet
|
||||
let packet = {
|
||||
let mut receiver = receiver.lock().await;
|
||||
let packet_size = receiver.read_u32().await?;
|
||||
let mut size_buf = [0u8; 4];
|
||||
receiver.read_exact(&mut size_buf).await?;
|
||||
let packet_size = u32::from_be_bytes(size_buf);
|
||||
log::trace!("packet size {}", packet_size);
|
||||
if packet_size > 128 * 1024 {
|
||||
anyhow::bail!("packet size too large (> 128 KiB)");
|
||||
|
|
@ -442,6 +472,6 @@ impl WayVRClient {
|
|||
impl Drop for WayVRClient {
|
||||
fn drop(&mut self) {
|
||||
self.exiting = true;
|
||||
self.cancel_token.cancel();
|
||||
let _ = self.cancel_tx.try_send(());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,29 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use tokio::sync::Notify;
|
||||
use async_channel::{Receiver, Sender};
|
||||
|
||||
// Copyable wrapped Notify struct for easier usage
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct Notifier {
|
||||
notifier: Arc<Notify>,
|
||||
sender: Sender<()>,
|
||||
receiver: Receiver<()>,
|
||||
}
|
||||
|
||||
impl Notifier {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
notifier: Arc::new(Notify::new()),
|
||||
}
|
||||
let (sender, receiver) = async_channel::bounded(1);
|
||||
Self { sender, receiver }
|
||||
}
|
||||
|
||||
pub fn notify(&self) {
|
||||
self.notifier.notify_waiters();
|
||||
let _ = self.sender.try_send(());
|
||||
}
|
||||
|
||||
pub async fn wait(&self) {
|
||||
self.notifier.notified().await;
|
||||
let _ = self.receiver.recv().await;
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Notifier {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,14 @@ wlx-capture = { path = "../wlx-capture" }
|
|||
wlx-common = { path = "../wlx-common" }
|
||||
|
||||
anyhow.workspace = true
|
||||
chrono = { workspace = true, features = ["unstable-locales"] }
|
||||
clap.workspace = true
|
||||
dbus.workspace = true
|
||||
glam = { workspace = true, features = ["mint", "serde"] }
|
||||
idmap = { workspace = true, features = ["serde"] }
|
||||
idmap-derive.workspace = true
|
||||
interprocess.workspace = true
|
||||
libc.workspace = true
|
||||
log.workspace = true
|
||||
pipewire = { workspace = true, optional = true }
|
||||
regex.workspace = true
|
||||
|
|
@ -40,17 +43,24 @@ serde = { workspace = true, features = ["rc"] }
|
|||
serde_json.workspace = true
|
||||
serde_json5.workspace = true
|
||||
slotmap.workspace = true
|
||||
smallvec.workspace = true
|
||||
smol = { workspace = true }
|
||||
strum.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
uuid = { workspace = true }
|
||||
vulkano.workspace = true
|
||||
vulkano-shaders.workspace = true
|
||||
wayland-client = { workspace = true }
|
||||
wayland-protocols = { workspace = true }
|
||||
wayland-protocols-misc = { workspace = true }
|
||||
winit = { workspace = true, optional = true }
|
||||
xdg.workspace = true
|
||||
|
||||
ash = "^0.38.0" # must match vulkano
|
||||
bytes = { workspace = true }
|
||||
chrono = { version = "0.4.42", features = ["unstable-locales"] }
|
||||
chrono-tz = "0.10.4"
|
||||
config = "0.15.19"
|
||||
futures = "0.3.31"
|
||||
config = "0.15.25"
|
||||
futures = "0.3.32"
|
||||
image_dds = {
|
||||
version = "0.7.2",
|
||||
default-features = false,
|
||||
|
|
@ -59,10 +69,8 @@ image_dds = {
|
|||
]
|
||||
}
|
||||
input-linux = "0.7.1"
|
||||
interprocess = { version = "2.2.3" }
|
||||
json = { version = "0.12.4", optional = true }
|
||||
json5 = "1.3.0"
|
||||
libc = "0.2.178"
|
||||
json5 = "1.3.1"
|
||||
libmonado = {
|
||||
git = "https://github.com/wayvr-org/libmonado-rs.git",
|
||||
rev = "6f66b26930c24a8a2fc57ddcd85704784894c750",
|
||||
|
|
@ -70,7 +78,7 @@ libmonado = {
|
|||
}
|
||||
log-panics = { version = "2.1.0", features = ["with-backtrace"] }
|
||||
mint = "0.5.9"
|
||||
openxr = { version = "0.21.0", features = ["linked", "mint"], optional = true }
|
||||
openxr = { version = "0.21.1", features = ["linked", "mint"], optional = true }
|
||||
ovr_overlay = {
|
||||
git = "https://github.com/galister/ovr_overlay_oyasumi",
|
||||
rev = "e477bd2a9e04293ea68c1e7529ef2cb131f32acc",
|
||||
|
|
@ -80,12 +88,11 @@ ovr_overlay = {
|
|||
],
|
||||
optional = true
|
||||
}
|
||||
prost = { version = "0.14.3", optional = true }
|
||||
prost = { version = "0.14.4", optional = true }
|
||||
pure-rust-locales = "0.8.2"
|
||||
rosc = { version = "0.11.4", optional = true }
|
||||
serde_yaml = "0.9.34"
|
||||
signal-hook = "0.3.18"
|
||||
smallvec = "1.15.1"
|
||||
serde_yaml = "0.9.33"
|
||||
signal-hook = "0.4.4"
|
||||
smithay = {
|
||||
version = "0.7.0",
|
||||
default-features = false,
|
||||
|
|
@ -97,19 +104,12 @@ smithay = {
|
|||
]
|
||||
}
|
||||
smithay-clipboard = "0.7.3"
|
||||
smol = { workspace = true }
|
||||
sysinfo = { version = "0.37" }
|
||||
thiserror = "2.0"
|
||||
tracing = "0.1.43"
|
||||
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
|
||||
uuid = { workspace = true }
|
||||
wayland-client = { workspace = true }
|
||||
wayland-protocols = { workspace = true }
|
||||
wayland-protocols-misc = { workspace = true }
|
||||
sysinfo = { version = "0.39.6" }
|
||||
thiserror = "2.0.18"
|
||||
tracing = "0.1.44"
|
||||
whisper-rs = { version = "0.16.0", features = ["vulkan"], optional = true }
|
||||
winit = { version = "0.30.12", optional = true }
|
||||
xcb = {
|
||||
version = "1.6.0",
|
||||
version = "1.7.0",
|
||||
features = [
|
||||
"as-raw-xcb-connection",
|
||||
],
|
||||
|
|
@ -119,8 +119,8 @@ xkbcommon = {
|
|||
version = "0.8.0"
|
||||
} # 0.9.0 breaks keymap import on some distros
|
||||
|
||||
calloop = { version = "0.14", optional = true }
|
||||
calloop-wayland-source = { version = "0.4", optional = true }
|
||||
calloop = { version = "0.14.4", optional = true }
|
||||
calloop-wayland-source = { version = "0.4.1", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
regex.workspace = true
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ authors = ["galister", "oo8dev"]
|
|||
repository = "https://github.com/wlx-team/wayvr"
|
||||
|
||||
[dependencies]
|
||||
wayvr-ipc = { path = "../wayvr-ipc" }
|
||||
|
||||
anyhow.workspace = true
|
||||
log.workspace = true
|
||||
clap.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
env_logger = "0.11.8"
|
||||
tokio = "1.48.0"
|
||||
wayvr-ipc = { path = "../wayvr-ipc" }
|
||||
smol.workspace = true
|
||||
|
||||
env_logger = "0.11.11"
|
||||
shell-words = "1.1.1"
|
||||
|
|
|
|||
|
|
@ -22,37 +22,38 @@ use crate::helper::{
|
|||
mod helper;
|
||||
mod types;
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> ExitCode {
|
||||
fn main() -> ExitCode {
|
||||
env_logger::init_from_env(Env::default().default_filter_or("info"));
|
||||
let args = Args::parse();
|
||||
|
||||
let mut state = WayVRClientState {
|
||||
wayvr_client: WayVRClient::new(&format!("wayvrctl-{}", process::id()))
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
log::error!("Failed to initialize WayVR connection: {e:?}");
|
||||
process::exit(1);
|
||||
})
|
||||
.unwrap(),
|
||||
serial_generator: ipc::SerialGenerator::new(),
|
||||
pretty_print: args.pretty,
|
||||
};
|
||||
smol::block_on(async move {
|
||||
let mut state = WayVRClientState {
|
||||
wayvr_client: WayVRClient::new(&format!("wayvrctl-{}", process::id()))
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
log::error!("Failed to initialize WayVR connection: {e:?}");
|
||||
process::exit(1);
|
||||
})
|
||||
.unwrap(),
|
||||
serial_generator: ipc::SerialGenerator::new(),
|
||||
pretty_print: args.pretty,
|
||||
};
|
||||
|
||||
let maybe_err = if let Subcommands::Batch { fail_fast } = args.command {
|
||||
run_batch(&mut state, fail_fast).await
|
||||
} else {
|
||||
run_once(&mut state, args).await
|
||||
};
|
||||
let maybe_err = if let Subcommands::Batch { fail_fast } = args.command {
|
||||
run_batch(&mut state, fail_fast).await
|
||||
} else {
|
||||
run_once(&mut state, args).await
|
||||
};
|
||||
|
||||
if let Err(e) = maybe_err {
|
||||
log::error!("{e:?}");
|
||||
return ExitCode::FAILURE;
|
||||
} else {
|
||||
std::thread::sleep(Duration::from_millis(20));
|
||||
}
|
||||
if let Err(e) = maybe_err {
|
||||
log::error!("{e:?}");
|
||||
return ExitCode::FAILURE;
|
||||
} else {
|
||||
std::thread::sleep(Duration::from_millis(20));
|
||||
}
|
||||
|
||||
ExitCode::SUCCESS
|
||||
ExitCode::SUCCESS
|
||||
})
|
||||
}
|
||||
|
||||
async fn run_batch(state: &mut WayVRClientState, fail_fast: bool) -> anyhow::Result<()> {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ image = {
|
|||
"webp",
|
||||
]
|
||||
}
|
||||
lru = "0.18.0"
|
||||
lru = "0.18.1"
|
||||
ouroboros = "0.18.5"
|
||||
parking_lot = "0.12.5"
|
||||
resvg = { version = "0.47.0", default-features = false }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ license = "GPL-3.0-only"
|
|||
[dependencies]
|
||||
dbus = { workspace = true, features = ["futures"], optional = true }
|
||||
idmap = { workspace = true }
|
||||
libc.workspace = true
|
||||
log = { workspace = true }
|
||||
pipewire = { workspace = true, optional = true }
|
||||
slotmap.workspace = true
|
||||
|
|
@ -29,7 +30,6 @@ wayland-protocols = {
|
|||
}
|
||||
|
||||
drm-fourcc = "2.2.0"
|
||||
libc = "0.2.178"
|
||||
rxscreen = {
|
||||
version = "0.1.7",
|
||||
features = [
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ license = "GPL-3.0-only"
|
|||
authors = ["galister", "oo8dev"]
|
||||
repository = "https://github.com/wlx-team/wayvr"
|
||||
|
||||
|
||||
[dependencies]
|
||||
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
|
||||
|
||||
anyhow.workspace = true
|
||||
chrono.workspace = true
|
||||
glam.workspace = true
|
||||
idmap = { workspace = true, features = ["serde"] }
|
||||
idmap-derive.workspace = true
|
||||
|
|
@ -19,14 +19,17 @@ log.workspace = true
|
|||
serde = { workspace = true, features = ["rc"] }
|
||||
serde_json.workspace = true
|
||||
serde_json5.workspace = true
|
||||
smol.workspace = true
|
||||
strum.workspace = true
|
||||
xdg.workspace = true
|
||||
|
||||
chrono = "0.4.42"
|
||||
smol = { workspace = true }
|
||||
wgui = { path = "../wgui/" }
|
||||
rodio = { version = "0.22.2", default-features = false, features = ["playback", "mp3", "hound", "recording"] }
|
||||
glob = "0.3.3"
|
||||
walkdir = "2.5.0"
|
||||
rust-ini = "0.21.3"
|
||||
identicons-svg = "0.1.0"
|
||||
rodio = {
|
||||
version = "0.22.2",
|
||||
default-features = false,
|
||||
features = ["hound", "mp3", "playback", "recording"]
|
||||
}
|
||||
rust-ini = "0.21.3"
|
||||
walkdir = "2.5.0"
|
||||
wgui = { path = "../wgui/" }
|
||||
|
|
|
|||
Loading…
Reference in New Issue