desktop almost working
This commit is contained in:
Generated
+257
-21
@@ -288,6 +288,33 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aws-lc-rs"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d"
|
||||||
|
dependencies = [
|
||||||
|
"aws-lc-sys",
|
||||||
|
"mirai-annotations",
|
||||||
|
"paste",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aws-lc-sys"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972"
|
||||||
|
dependencies = [
|
||||||
|
"bindgen",
|
||||||
|
"cc",
|
||||||
|
"cmake",
|
||||||
|
"dunce",
|
||||||
|
"fs_extra",
|
||||||
|
"libc",
|
||||||
|
"paste",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.73"
|
version = "0.3.73"
|
||||||
@@ -318,6 +345,29 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bindgen"
|
||||||
|
version = "0.69.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"cexpr",
|
||||||
|
"clang-sys",
|
||||||
|
"itertools",
|
||||||
|
"lazy_static",
|
||||||
|
"lazycell",
|
||||||
|
"log",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"rustc-hash",
|
||||||
|
"shlex",
|
||||||
|
"syn 2.0.68",
|
||||||
|
"which",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -441,6 +491,11 @@ name = "cc"
|
|||||||
version = "1.0.104"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490"
|
checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490"
|
||||||
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cesu8"
|
name = "cesu8"
|
||||||
@@ -448,6 +503,15 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cexpr"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfb"
|
name = "cfb"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
@@ -514,6 +578,26 @@ dependencies = [
|
|||||||
"half",
|
"half",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clang-sys"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||||
|
dependencies = [
|
||||||
|
"glob",
|
||||||
|
"libc",
|
||||||
|
"libloading",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cmake"
|
||||||
|
version = "0.1.51"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cocoa"
|
name = "cocoa"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
@@ -1191,6 +1275,12 @@ version = "1.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.34"
|
version = "0.8.34"
|
||||||
@@ -1393,6 +1483,12 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs_extra"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futf"
|
name = "futf"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -1739,6 +1835,12 @@ dependencies = [
|
|||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "global-hotkey"
|
name = "global-hotkey"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
@@ -2325,6 +2427,15 @@ version = "2.9.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
@@ -2382,6 +2493,15 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.70"
|
version = "0.3.70"
|
||||||
@@ -2446,6 +2566,16 @@ version = "0.2.155"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libxdo"
|
name = "libxdo"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@@ -2689,15 +2819,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.9",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mirai-annotations"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "muda"
|
name = "muda"
|
||||||
version = "0.11.5"
|
version = "0.11.5"
|
||||||
@@ -2731,7 +2868,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mumble-webtransport"
|
name = "mumble-web2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -2754,6 +2891,8 @@ dependencies = [
|
|||||||
"serde-wasm-bindgen 0.6.5",
|
"serde-wasm-bindgen 0.6.5",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sir",
|
"sir",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
@@ -2891,16 +3030,6 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi 0.3.9",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
@@ -3117,6 +3246,12 @@ dependencies = [
|
|||||||
"windows-targets 0.52.5",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
@@ -3637,6 +3772,21 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.17.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom 0.2.15",
|
||||||
|
"libc",
|
||||||
|
"spin",
|
||||||
|
"untrusted",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rsass"
|
name = "rsass"
|
||||||
version = "0.28.10"
|
version = "0.28.10"
|
||||||
@@ -3688,6 +3838,21 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.23.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e"
|
||||||
|
dependencies = [
|
||||||
|
"aws-lc-rs",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"rustls-webpki",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pemfile"
|
name = "rustls-pemfile"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -3697,6 +3862,24 @@ dependencies = [
|
|||||||
"base64",
|
"base64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pki-types"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.102.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
|
||||||
|
dependencies = [
|
||||||
|
"aws-lc-rs",
|
||||||
|
"ring",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
@@ -3988,6 +4171,12 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
@@ -4135,6 +4324,12 @@ dependencies = [
|
|||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spinning"
|
name = "spinning"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -4182,6 +4377,12 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
@@ -4381,26 +4582,25 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.38.0"
|
version = "1.41.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -4417,6 +4617,17 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.26.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.11"
|
version = "0.7.11"
|
||||||
@@ -4425,6 +4636,7 @@ checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -4636,6 +4848,12 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.5.2"
|
version = "2.5.2"
|
||||||
@@ -4908,6 +5126,18 @@ dependencies = [
|
|||||||
"windows-core 0.52.0",
|
"windows-core 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "which"
|
||||||
|
version = "4.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"home",
|
||||||
|
"once_cell",
|
||||||
|
"rustix",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -4930,7 +5160,7 @@ version = "0.1.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5442,6 +5672,12 @@ dependencies = [
|
|||||||
"syn 2.0.68",
|
"syn 2.0.68",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "4.2.0"
|
version = "4.2.0"
|
||||||
|
|||||||
+5
-3
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mumble-webtransport"
|
name = "mumble-web2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ futures = "0.3.30"
|
|||||||
merge-io = "0.3.0"
|
merge-io = "0.3.0"
|
||||||
mumble-protocol = { version = "0.5.0", package = "mumble-protocol-2x", default-features = false, features = ["asynchronous-codec"]}
|
mumble-protocol = { version = "0.5.0", package = "mumble-protocol-2x", default-features = false, features = ["asynchronous-codec"]}
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
tokio-util = { version = "0.7.11", features = ["codec"]}
|
tokio-util = { version = "0.7.11", features = ["codec", "compat"]}
|
||||||
wasm-bindgen = { version = "0.2.92", optional = true }
|
wasm-bindgen = { version = "0.2.92", optional = true }
|
||||||
wasm-bindgen-futures = { version = "0.4.42", optional = true }
|
wasm-bindgen-futures = { version = "0.4.42", optional = true }
|
||||||
wasm-streams = { version = "0.4.0", optional = true }
|
wasm-streams = { version = "0.4.0", optional = true }
|
||||||
@@ -29,7 +29,9 @@ markdown = "0.3.0"
|
|||||||
gloo-timers = { version = "0.3.0", features = ["futures"] }
|
gloo-timers = { version = "0.3.0", features = ["futures"] }
|
||||||
futures-channel = "0.3.30"
|
futures-channel = "0.3.30"
|
||||||
sir = { version = "0.5.0", features = ["dioxus"] }
|
sir = { version = "0.5.0", features = ["dioxus"] }
|
||||||
|
tokio = { version = "1.41.1", features = ["net", "rt"], optional = true }
|
||||||
|
tokio-rustls = { version = "0.26.0", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
web = ["dioxus/web", "dioxus-web", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "serde-wasm-bindgen", "js-sys", "web-sys"]
|
web = ["dioxus/web", "dioxus-web", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "serde-wasm-bindgen", "js-sys", "web-sys"]
|
||||||
desktop = ["dioxus/desktop"]
|
desktop = ["dioxus/desktop", "tokio", "tokio-rustls"]
|
||||||
|
|||||||
+111
-8
@@ -1,6 +1,22 @@
|
|||||||
use crate::app::Command;
|
use crate::app::Command;
|
||||||
use dioxus::hooks::UnboundedReceiver;
|
use anyhow::Result;
|
||||||
use std::{fmt, io};
|
use dioxus::hooks::{UnboundedReceiver, UnboundedSender};
|
||||||
|
use mumble_protocol::control::{ClientControlCodec, ControlPacket};
|
||||||
|
use mumble_protocol::Serverbound;
|
||||||
|
use std::net::ToSocketAddrs;
|
||||||
|
use std::{fmt, io, sync::Arc};
|
||||||
|
use tokio::net::TcpStream;
|
||||||
|
use tokio::task::LocalSet;
|
||||||
|
use tokio_rustls::rustls;
|
||||||
|
use tokio_rustls::rustls::client::danger::{HandshakeSignatureValid, ServerCertVerifier};
|
||||||
|
use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime};
|
||||||
|
use tokio_rustls::rustls::ClientConfig;
|
||||||
|
use tokio_rustls::rustls::DigitallySignedStruct;
|
||||||
|
use tokio_rustls::TlsConnector;
|
||||||
|
use tokio_util::compat::{TokioAsyncReadCompatExt as _, TokioAsyncWriteCompatExt as _};
|
||||||
|
|
||||||
|
pub use tokio::task::spawn_local as spawn;
|
||||||
|
pub use tokio::time::sleep;
|
||||||
|
|
||||||
pub struct Error(anyhow::Error);
|
pub struct Error(anyhow::Error);
|
||||||
|
|
||||||
@@ -40,7 +56,19 @@ impl fmt::Debug for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AudioContext();
|
pub struct AudioSystem();
|
||||||
|
|
||||||
|
impl AudioSystem {
|
||||||
|
pub fn new(sender: UnboundedSender<ControlPacket<Serverbound>>) -> Result<Self, Error> {
|
||||||
|
dbg!("todo");
|
||||||
|
Ok(AudioSystem())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_player(&mut self) -> Result<AudioPlayer, Error> {
|
||||||
|
dbg!("todo");
|
||||||
|
Ok(AudioPlayer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AudioPlayer();
|
pub struct AudioPlayer();
|
||||||
|
|
||||||
@@ -50,15 +78,90 @@ impl AudioPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct NoCertificateVerification;
|
||||||
|
|
||||||
|
impl ServerCertVerifier for NoCertificateVerification {
|
||||||
|
fn verify_server_cert(
|
||||||
|
&self,
|
||||||
|
_end_entity: &CertificateDer<'_>,
|
||||||
|
_intermediates: &[CertificateDer<'_>],
|
||||||
|
_server_name: &ServerName<'_>,
|
||||||
|
_ocsp: &[u8],
|
||||||
|
_now: UnixTime,
|
||||||
|
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
|
||||||
|
Ok(rustls::client::danger::ServerCertVerified::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_tls12_signature(
|
||||||
|
&self,
|
||||||
|
_message: &[u8],
|
||||||
|
_cert: &CertificateDer<'_>,
|
||||||
|
_dss: &DigitallySignedStruct,
|
||||||
|
) -> Result<HandshakeSignatureValid, rustls::Error> {
|
||||||
|
Ok(HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_tls13_signature(
|
||||||
|
&self,
|
||||||
|
_message: &[u8],
|
||||||
|
_cert: &CertificateDer<'_>,
|
||||||
|
_dss: &DigitallySignedStruct,
|
||||||
|
) -> Result<HandshakeSignatureValid, rustls::Error> {
|
||||||
|
Ok(HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||||
|
vec![
|
||||||
|
rustls::SignatureScheme::RSA_PKCS1_SHA1,
|
||||||
|
rustls::SignatureScheme::ECDSA_SHA1_Legacy,
|
||||||
|
rustls::SignatureScheme::RSA_PKCS1_SHA256,
|
||||||
|
rustls::SignatureScheme::ECDSA_NISTP256_SHA256,
|
||||||
|
rustls::SignatureScheme::RSA_PKCS1_SHA384,
|
||||||
|
rustls::SignatureScheme::ECDSA_NISTP384_SHA384,
|
||||||
|
rustls::SignatureScheme::RSA_PKCS1_SHA512,
|
||||||
|
rustls::SignatureScheme::ECDSA_NISTP521_SHA512,
|
||||||
|
rustls::SignatureScheme::RSA_PSS_SHA256,
|
||||||
|
rustls::SignatureScheme::RSA_PSS_SHA384,
|
||||||
|
rustls::SignatureScheme::RSA_PSS_SHA512,
|
||||||
|
rustls::SignatureScheme::ED25519,
|
||||||
|
rustls::SignatureScheme::ED448,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn network_connect(
|
pub async fn network_connect(
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
event_rx: &mut UnboundedReceiver<Command>,
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
dbg!("todo");
|
let localset = LocalSet::new();
|
||||||
Ok(())
|
let _guard = localset.enter();
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_player(ctx: &AudioContext) -> Result<AudioPlayer, Error> {
|
let config = ClientConfig::builder()
|
||||||
Ok(AudioPlayer())
|
.dangerous()
|
||||||
|
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification))
|
||||||
|
.with_no_client_auth();
|
||||||
|
|
||||||
|
let connector = TlsConnector::from(Arc::new(config));
|
||||||
|
|
||||||
|
let addr = format!("{}:{}", address, 64738)
|
||||||
|
.to_socket_addrs()?
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let server_tcp = TcpStream::connect(addr).await?;
|
||||||
|
let server_stream = connector
|
||||||
|
//.connect("127.0.0.1".try_into()?, server_tcp)
|
||||||
|
.connect(address.try_into().map_err(anyhow::Error::from)?, server_tcp)
|
||||||
|
.await?;
|
||||||
|
let (read_server, write_server) = tokio::io::split(server_stream);
|
||||||
|
|
||||||
|
let read_codec = ClientControlCodec::new();
|
||||||
|
let write_codec = ClientControlCodec::new();
|
||||||
|
|
||||||
|
let mut reader = asynchronous_codec::FramedRead::new(read_server.compat(), read_codec);
|
||||||
|
let mut writer = asynchronous_codec::FramedWrite::new(write_server.compat_write(), write_codec);
|
||||||
|
|
||||||
|
super::network_loop(username, event_rx, reader, writer).await
|
||||||
}
|
}
|
||||||
|
|||||||
+96
-174
@@ -1,26 +1,24 @@
|
|||||||
use crate::app::Command;
|
use crate::app::Command;
|
||||||
use crate::bail;
|
use crate::bail;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use futures::select;
|
|
||||||
use futures::FutureExt;
|
|
||||||
use futures::SinkExt;
|
|
||||||
use futures::StreamExt;
|
|
||||||
use futures_channel::mpsc::UnboundedSender;
|
use futures_channel::mpsc::UnboundedSender;
|
||||||
use gloo_timers::future::TimeoutFuture;
|
use gloo_timers::future::TimeoutFuture;
|
||||||
|
use mumble_protocol::control::ClientControlCodec;
|
||||||
use mumble_protocol::control::ControlPacket;
|
use mumble_protocol::control::ControlPacket;
|
||||||
use mumble_protocol::control::{msgs, ClientControlCodec};
|
|
||||||
use mumble_protocol::voice::VoicePacket;
|
use mumble_protocol::voice::VoicePacket;
|
||||||
use mumble_protocol::voice::VoicePacketPayload;
|
use mumble_protocol::voice::VoicePacketPayload;
|
||||||
use std::collections::HashMap;
|
use mumble_protocol::Serverbound;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
|
use std::time::Duration;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen_futures::spawn_local as spawn;
|
|
||||||
use wasm_bindgen_futures::JsFuture;
|
use wasm_bindgen_futures::JsFuture;
|
||||||
use web_sys::console;
|
use web_sys::console;
|
||||||
use web_sys::js_sys::Promise;
|
use web_sys::js_sys::Promise;
|
||||||
use web_sys::js_sys::Reflect;
|
use web_sys::js_sys::Reflect;
|
||||||
use web_sys::js_sys::Uint8Array;
|
use web_sys::js_sys::Uint8Array;
|
||||||
use web_sys::window;
|
use web_sys::window;
|
||||||
|
use web_sys::AudioContext;
|
||||||
use web_sys::AudioContextOptions;
|
use web_sys::AudioContextOptions;
|
||||||
use web_sys::AudioData;
|
use web_sys::AudioData;
|
||||||
use web_sys::AudioDecoder;
|
use web_sys::AudioDecoder;
|
||||||
@@ -43,7 +41,11 @@ use web_sys::WebTransportBidirectionalStream;
|
|||||||
use web_sys::WebTransportOptions;
|
use web_sys::WebTransportOptions;
|
||||||
use web_sys::WorkletOptions;
|
use web_sys::WorkletOptions;
|
||||||
|
|
||||||
pub use web_sys::AudioContext;
|
pub use wasm_bindgen_futures::spawn_local as spawn;
|
||||||
|
|
||||||
|
pub async fn sleep(d: Duration) {
|
||||||
|
TimeoutFuture::new(d.as_millis() as u32).await
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Error(JsValue);
|
pub struct Error(JsValue);
|
||||||
|
|
||||||
@@ -53,6 +55,12 @@ impl From<anyhow::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(value: io::Error) -> Self {
|
||||||
|
Error(JsError::new(&value.to_string()).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<JsValue> for Error {
|
impl From<JsValue> for Error {
|
||||||
fn from(value: JsValue) -> Self {
|
fn from(value: JsValue) -> Self {
|
||||||
Error(value)
|
Error(value)
|
||||||
@@ -91,6 +99,83 @@ impl fmt::Debug for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AudioSystem(AudioContext);
|
||||||
|
|
||||||
|
impl AudioSystem {
|
||||||
|
pub fn new(sender: UnboundedSender<ControlPacket<Serverbound>>) -> Result<Self, Error> {
|
||||||
|
// Create MediaStreams to playback decoded audio
|
||||||
|
// The audio context is used to reproduce audio.
|
||||||
|
let audio_context = configure_audio_context();
|
||||||
|
|
||||||
|
let audio_context_worklet = audio_context.clone();
|
||||||
|
spawn(async move {
|
||||||
|
match create_encoder_worklet(&audio_context_worklet, sender).await {
|
||||||
|
Ok(node) => console::log_2(&"Created audio worklet:".into(), &node),
|
||||||
|
Err(err) => err.log(),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(AudioSystem(audio_context))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_player(&mut self) -> Result<AudioPlayer, Error> {
|
||||||
|
let audio_context = &self.0;
|
||||||
|
|
||||||
|
let audio_stream_generator =
|
||||||
|
MediaStreamTrackGenerator::new(&MediaStreamTrackGeneratorInit::new("audio"))?;
|
||||||
|
|
||||||
|
// Create MediaStream from MediaStreamTrackGenerator
|
||||||
|
let js_tracks = web_sys::js_sys::Array::new();
|
||||||
|
js_tracks.push(&audio_stream_generator);
|
||||||
|
let media_stream = MediaStream::new_with_tracks(&js_tracks)?;
|
||||||
|
|
||||||
|
// Create MediaStreamAudioSourceNode
|
||||||
|
let audio_source = audio_context.create_media_stream_source(&media_stream)?;
|
||||||
|
// Connect output of audio_source to audio_context (browser audio)
|
||||||
|
audio_source.connect_with_audio_node(&audio_context.destination())?;
|
||||||
|
|
||||||
|
// Create callback functions for AudioDecoder
|
||||||
|
let error = Closure::wrap(Box::new(move |e: JsValue| {
|
||||||
|
console::error_1(&e);
|
||||||
|
}) as Box<dyn FnMut(JsValue)>);
|
||||||
|
|
||||||
|
// This knows what MediaStreamTrackGenerator to use as it closes around it
|
||||||
|
let output = Closure::wrap(Box::new(move |audio_data: AudioData| {
|
||||||
|
let writable = audio_stream_generator.writable();
|
||||||
|
if writable.locked() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Err(e) = writable.get_writer().map(|writer| {
|
||||||
|
spawn(async move {
|
||||||
|
if let Err(e) = JsFuture::from(writer.ready()).await {
|
||||||
|
console::error_1(&format!("write chunk ready error {:?}", e).into());
|
||||||
|
}
|
||||||
|
if let Err(e) = JsFuture::from(writer.write_with_chunk(&audio_data)).await {
|
||||||
|
console::error_1(&format!("write chunk error {:?}", e).into());
|
||||||
|
};
|
||||||
|
writer.release_lock();
|
||||||
|
});
|
||||||
|
}) {
|
||||||
|
console::error_1(&e);
|
||||||
|
}
|
||||||
|
}) as Box<dyn FnMut(AudioData)>);
|
||||||
|
|
||||||
|
let audio_decoder = AudioDecoder::new(&AudioDecoderInit::new(
|
||||||
|
error.as_ref().unchecked_ref(),
|
||||||
|
output.as_ref().unchecked_ref(),
|
||||||
|
))?;
|
||||||
|
|
||||||
|
audio_decoder.configure(&AudioDecoderConfig::new("opus", 1, 48000));
|
||||||
|
console::log_1(&"Created Audio Decoder".into());
|
||||||
|
|
||||||
|
// This is required to prevent these from being deallocated
|
||||||
|
error.forget();
|
||||||
|
output.forget();
|
||||||
|
|
||||||
|
Ok(AudioPlayer(audio_decoder))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AudioPlayer(AudioDecoder);
|
pub struct AudioPlayer(AudioDecoder);
|
||||||
|
|
||||||
impl AudioPlayer {
|
impl AudioPlayer {
|
||||||
@@ -245,61 +330,6 @@ async fn create_encoder_worklet(
|
|||||||
Ok(worklet_node)
|
Ok(worklet_node)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_player(audio_context: &AudioContext) -> Result<AudioPlayer, Error> {
|
|
||||||
let audio_stream_generator =
|
|
||||||
MediaStreamTrackGenerator::new(&MediaStreamTrackGeneratorInit::new("audio"))?;
|
|
||||||
|
|
||||||
// Create MediaStream from MediaStreamTrackGenerator
|
|
||||||
let js_tracks = web_sys::js_sys::Array::new();
|
|
||||||
js_tracks.push(&audio_stream_generator);
|
|
||||||
let media_stream = MediaStream::new_with_tracks(&js_tracks)?;
|
|
||||||
|
|
||||||
// Create MediaStreamAudioSourceNode
|
|
||||||
let audio_source = audio_context.create_media_stream_source(&media_stream)?;
|
|
||||||
// Connect output of audio_source to audio_context (browser audio)
|
|
||||||
audio_source.connect_with_audio_node(&audio_context.destination())?;
|
|
||||||
|
|
||||||
// Create callback functions for AudioDecoder
|
|
||||||
let error = Closure::wrap(Box::new(move |e: JsValue| {
|
|
||||||
console::error_1(&e);
|
|
||||||
}) as Box<dyn FnMut(JsValue)>);
|
|
||||||
|
|
||||||
// This knows what MediaStreamTrackGenerator to use as it closes around it
|
|
||||||
let output = Closure::wrap(Box::new(move |audio_data: AudioData| {
|
|
||||||
let writable = audio_stream_generator.writable();
|
|
||||||
if writable.locked() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if let Err(e) = writable.get_writer().map(|writer| {
|
|
||||||
spawn(async move {
|
|
||||||
if let Err(e) = JsFuture::from(writer.ready()).await {
|
|
||||||
console::error_1(&format!("write chunk ready error {:?}", e).into());
|
|
||||||
}
|
|
||||||
if let Err(e) = JsFuture::from(writer.write_with_chunk(&audio_data)).await {
|
|
||||||
console::error_1(&format!("write chunk error {:?}", e).into());
|
|
||||||
};
|
|
||||||
writer.release_lock();
|
|
||||||
});
|
|
||||||
}) {
|
|
||||||
console::error_1(&e);
|
|
||||||
}
|
|
||||||
}) as Box<dyn FnMut(AudioData)>);
|
|
||||||
|
|
||||||
let audio_decoder = AudioDecoder::new(&AudioDecoderInit::new(
|
|
||||||
error.as_ref().unchecked_ref(),
|
|
||||||
output.as_ref().unchecked_ref(),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
audio_decoder.configure(&AudioDecoderConfig::new("opus", 1, 48000));
|
|
||||||
console::log_1(&"Created Audio Decoder".into());
|
|
||||||
|
|
||||||
// This is required to prevent these from being deallocated
|
|
||||||
error.forget();
|
|
||||||
output.forget();
|
|
||||||
|
|
||||||
Ok(AudioPlayer(audio_decoder))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn network_connect(
|
pub async fn network_connect(
|
||||||
address: String,
|
address: String,
|
||||||
username: String,
|
username: String,
|
||||||
@@ -360,118 +390,10 @@ pub async fn network_connect(
|
|||||||
let read_codec = ClientControlCodec::new();
|
let read_codec = ClientControlCodec::new();
|
||||||
let write_codec = ClientControlCodec::new();
|
let write_codec = ClientControlCodec::new();
|
||||||
|
|
||||||
let mut reader =
|
let reader =
|
||||||
asynchronous_codec::FramedRead::new(wasm_stream_readable.into_async_read(), read_codec);
|
asynchronous_codec::FramedRead::new(wasm_stream_readable.into_async_read(), read_codec);
|
||||||
let mut writer =
|
let writer =
|
||||||
asynchronous_codec::FramedWrite::new(wasm_stream_writable.into_async_write(), write_codec);
|
asynchronous_codec::FramedWrite::new(wasm_stream_writable.into_async_write(), write_codec);
|
||||||
|
|
||||||
let (mut send_chan, mut writer_recv_chan) = futures_channel::mpsc::unbounded();
|
super::network_loop(username, event_rx, reader, writer).await
|
||||||
|
|
||||||
// Spawn worker to send packets.
|
|
||||||
spawn(async move {
|
|
||||||
while let Some(msg) = writer_recv_chan.next().await {
|
|
||||||
if !matches!(msg, ControlPacket::Ping(_) | ControlPacket::UDPTunnel(_)) {
|
|
||||||
console::log_1(&format!("sending {:#?}", msg).into());
|
|
||||||
}
|
|
||||||
if let Err(e) = writer.send(msg).await {
|
|
||||||
console::error_1(&e.to_string().into());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get version packet
|
|
||||||
let version = match reader.next().await {
|
|
||||||
Some(Ok(v)) => v,
|
|
||||||
Some(Err(err)) => bail!("bad version packet: {err:?}"),
|
|
||||||
None => bail!("no version was recieved"),
|
|
||||||
};
|
|
||||||
console::log_1(&"Got version packet".into());
|
|
||||||
console::log_1(&format!("{:#?}", version).into());
|
|
||||||
|
|
||||||
// Send version packet
|
|
||||||
let mut msg = msgs::Version::new();
|
|
||||||
msg.set_version(0x000010204);
|
|
||||||
msg.set_release(format!("{} {}", "mumbleweb2", "6.9.0"));
|
|
||||||
//msg.set_os("Chrome".to_string());
|
|
||||||
send_chan.send(msg.into()).await.unwrap();
|
|
||||||
|
|
||||||
// Send authenticate packet
|
|
||||||
let mut msg = msgs::Authenticate::new();
|
|
||||||
msg.set_username(username);
|
|
||||||
msg.set_opus(true);
|
|
||||||
send_chan.send(msg.into()).await.unwrap();
|
|
||||||
|
|
||||||
// Spawn worker to send pings
|
|
||||||
{
|
|
||||||
let mut send_chan = send_chan.clone();
|
|
||||||
spawn(async move {
|
|
||||||
loop {
|
|
||||||
if let Err(e) = send_chan.send(msgs::Ping::new().into()).await {
|
|
||||||
console::log_1(&"could not ping".into());
|
|
||||||
console::log_1(&e.to_string().into());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeoutFuture::new(3000).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create MediaStreams to playback decoded audio
|
|
||||||
// The audio context is used to reproduce audio.
|
|
||||||
let audio_context = configure_audio_context();
|
|
||||||
|
|
||||||
let audio_context_worklet = audio_context.clone();
|
|
||||||
let packet_sender_worklet = send_chan.clone();
|
|
||||||
spawn(async move {
|
|
||||||
match create_encoder_worklet(&audio_context_worklet, packet_sender_worklet).await {
|
|
||||||
Ok(node) => console::log_2(&"Created audio worklet:".into(), &node),
|
|
||||||
Err(err) => err.log(),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create map of session_id -> AudioDecoder
|
|
||||||
let mut decoder_map = HashMap::new();
|
|
||||||
|
|
||||||
let mut reader_future = reader.next().fuse();
|
|
||||||
let mut command_future = event_rx.next();
|
|
||||||
loop {
|
|
||||||
select! {
|
|
||||||
packet = reader_future => {
|
|
||||||
reader_future = reader.next().fuse();
|
|
||||||
match packet {
|
|
||||||
Some(Ok(msg)) => {
|
|
||||||
if !matches!(msg, ControlPacket::UDPTunnel(_) | ControlPacket::Ping(_)) {
|
|
||||||
console::log_1(&format!("receiving {:#?}", msg).into());
|
|
||||||
}
|
|
||||||
let res = super::accept_packet(msg, &audio_context, &mut decoder_map);
|
|
||||||
if let Err(err) = res {
|
|
||||||
err.log();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(Err(err)) => console::error_1(&err.to_string().into()),
|
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
command = command_future => {
|
|
||||||
command_future = event_rx.next();
|
|
||||||
if let Some(command) = &command {
|
|
||||||
console::log_1(&format!("commanding {:#?}", command).into());
|
|
||||||
}
|
|
||||||
match command {
|
|
||||||
Some(Command::Disconnect) => break,
|
|
||||||
Some(command) => {
|
|
||||||
let res = super::accept_command(command, &mut send_chan);
|
|
||||||
if let Err(err) = res {
|
|
||||||
err.log();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => continue,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let _ = send_chan.close();
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
+127
-2
@@ -2,15 +2,32 @@ use app::Chat;
|
|||||||
use app::Command;
|
use app::Command;
|
||||||
use app::ConnectionState;
|
use app::ConnectionState;
|
||||||
use app::STATE;
|
use app::STATE;
|
||||||
|
use asynchronous_codec::FramedRead;
|
||||||
|
use asynchronous_codec::FramedWrite;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use futures::io::AsyncRead;
|
||||||
|
use futures::io::AsyncWrite;
|
||||||
|
use futures::select;
|
||||||
|
use futures::FutureExt as _;
|
||||||
|
use futures::Sink;
|
||||||
|
use futures::SinkExt as _;
|
||||||
|
use futures::Stream;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use futures_channel::mpsc::UnboundedSender;
|
use futures_channel::mpsc::UnboundedSender;
|
||||||
|
pub use imp::spawn;
|
||||||
pub use imp::Error;
|
pub use imp::Error;
|
||||||
use mumble_protocol::control::msgs;
|
use mumble_protocol::control::msgs;
|
||||||
|
use mumble_protocol::control::ControlCodec;
|
||||||
use mumble_protocol::control::ControlPacket;
|
use mumble_protocol::control::ControlPacket;
|
||||||
use mumble_protocol::voice::VoicePacketPayload;
|
use mumble_protocol::voice::VoicePacketPayload;
|
||||||
|
use mumble_protocol::Clientbound;
|
||||||
|
use mumble_protocol::Serverbound;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::io;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
pub mod app;
|
pub mod app;
|
||||||
|
|
||||||
@@ -51,6 +68,114 @@ pub async fn network_entrypoint(mut event_rx: UnboundedReceiver<Command>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn network_loop<R, W>(
|
||||||
|
username: String,
|
||||||
|
event_rx: &mut UnboundedReceiver<Command>,
|
||||||
|
mut reader: FramedRead<R, ControlCodec<Serverbound, Clientbound>>,
|
||||||
|
mut writer: FramedWrite<W, ControlCodec<Serverbound, Clientbound>>,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
R: AsyncRead + Unpin + 'static,
|
||||||
|
W: AsyncWrite + Unpin + 'static,
|
||||||
|
{
|
||||||
|
let (mut send_chan, mut writer_recv_chan) = futures_channel::mpsc::unbounded();
|
||||||
|
spawn(async move {
|
||||||
|
while let Some(msg) = writer_recv_chan.next().await {
|
||||||
|
if !matches!(msg, ControlPacket::Ping(_) | ControlPacket::UDPTunnel(_)) {
|
||||||
|
eprintln!("sending {:#?}", msg);
|
||||||
|
}
|
||||||
|
if let Err(e) = writer.send(msg).await {
|
||||||
|
eprintln!("ERROR: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get version packet
|
||||||
|
let version = match reader.next().await {
|
||||||
|
Some(Ok(v)) => v,
|
||||||
|
Some(Err(err)) => bail!("bad version packet: {err:?}"),
|
||||||
|
None => bail!("no version was recieved"),
|
||||||
|
};
|
||||||
|
println!("Got version packet");
|
||||||
|
println!("{:#?}", version);
|
||||||
|
|
||||||
|
// Send version packet
|
||||||
|
let mut msg = msgs::Version::new();
|
||||||
|
msg.set_version(0x000010204);
|
||||||
|
msg.set_release(format!("{} {}", "mumbleweb2", "6.9.0"));
|
||||||
|
//msg.set_os("Chrome".to_string());
|
||||||
|
send_chan.send(msg.into()).await.unwrap();
|
||||||
|
|
||||||
|
// Send authenticate packet
|
||||||
|
let mut msg = msgs::Authenticate::new();
|
||||||
|
msg.set_username(username);
|
||||||
|
msg.set_opus(true);
|
||||||
|
send_chan.send(msg.into()).await.unwrap();
|
||||||
|
|
||||||
|
// Spawn worker to send pings
|
||||||
|
{
|
||||||
|
let mut send_chan = send_chan.clone();
|
||||||
|
spawn(async move {
|
||||||
|
loop {
|
||||||
|
if let Err(_) = send_chan.send(msgs::Ping::new().into()).await {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
imp::sleep(Duration::from_millis(3000)).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut audio = imp::AudioSystem::new(send_chan.clone())?;
|
||||||
|
|
||||||
|
// Create map of session_id -> AudioDecoder
|
||||||
|
let mut decoder_map = HashMap::new();
|
||||||
|
|
||||||
|
let mut reader_future = reader.next().fuse();
|
||||||
|
let mut command_future = event_rx.next();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
packet = reader_future => {
|
||||||
|
reader_future = reader.next().fuse();
|
||||||
|
match packet {
|
||||||
|
Some(Ok(msg)) => {
|
||||||
|
if !matches!(msg, ControlPacket::UDPTunnel(_) | ControlPacket::Ping(_)) {
|
||||||
|
println!("receiving {:#?}", msg);
|
||||||
|
}
|
||||||
|
let res = accept_packet(msg, &mut audio, &mut decoder_map);
|
||||||
|
if let Err(err) = res {
|
||||||
|
err.log();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(Err(err)) => Error::from(err).log(),
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
command = command_future => {
|
||||||
|
command_future = event_rx.next();
|
||||||
|
if let Some(command) = &command {
|
||||||
|
println!("commanding {:#?}", command);
|
||||||
|
}
|
||||||
|
match command {
|
||||||
|
Some(Command::Disconnect) => break,
|
||||||
|
Some(command) => {
|
||||||
|
let res = accept_command(command, &mut send_chan);
|
||||||
|
if let Err(err) = res {
|
||||||
|
err.log();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = send_chan.close();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn accept_command(
|
fn accept_command(
|
||||||
command: Command,
|
command: Command,
|
||||||
send_chan: &mut UnboundedSender<ControlPacket<mumble_protocol::Serverbound>>,
|
send_chan: &mut UnboundedSender<ControlPacket<mumble_protocol::Serverbound>>,
|
||||||
@@ -98,7 +223,7 @@ fn accept_command(
|
|||||||
|
|
||||||
fn accept_packet(
|
fn accept_packet(
|
||||||
msg: ControlPacket<mumble_protocol::Clientbound>,
|
msg: ControlPacket<mumble_protocol::Clientbound>,
|
||||||
audio_context: &imp::AudioContext,
|
audio_context: &mut imp::AudioSystem,
|
||||||
player_map: &mut HashMap<u32, imp::AudioPlayer>,
|
player_map: &mut HashMap<u32, imp::AudioPlayer>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match msg {
|
match msg {
|
||||||
@@ -116,7 +241,7 @@ fn accept_packet(
|
|||||||
let audio_player = match player_map.entry(session_id) {
|
let audio_player = match player_map.entry(session_id) {
|
||||||
Entry::Occupied(occupied_entry) => occupied_entry.into_mut(),
|
Entry::Occupied(occupied_entry) => occupied_entry.into_mut(),
|
||||||
Entry::Vacant(vacant_entry) => {
|
Entry::Vacant(vacant_entry) => {
|
||||||
vacant_entry.insert(imp::create_player(&audio_context)?)
|
vacant_entry.insert(audio_context.create_player()?)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// This will over time (as users join and leave) leak
|
// This will over time (as users join and leave) leak
|
||||||
|
|||||||
+7
-1
@@ -1,5 +1,11 @@
|
|||||||
use mumble_webtransport::app;
|
use mumble_web2::app;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
#[cfg(feature = "desktop")]
|
||||||
|
let _guard = tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.enter();
|
||||||
dioxus::launch(app::app);
|
dioxus::launch(app::app);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user