diff --git a/Cargo.lock b/Cargo.lock index f78638c..0eb1114 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -62,6 +68,36 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "ashpd" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.8.5", + "serde", + "serde_repr", + "url", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-channel" version = "2.3.1" @@ -74,6 +110,119 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "async-signal" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.52.0", +] + [[package]] name = "async-task" version = "4.7.1" @@ -104,6 +253,29 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "atk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -126,7 +298,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -161,6 +333,21 @@ dependencies = [ "serde", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "blocking" version = "1.6.1" @@ -192,6 +379,31 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.6.0", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + [[package]] name = "camino" version = "1.1.7" @@ -230,6 +442,12 @@ version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfb" version = "0.7.3" @@ -248,6 +466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", + "target-lexicon", ] [[package]] @@ -256,6 +475,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "ciborium" version = "0.2.2" @@ -283,6 +514,46 @@ dependencies = [ "half", ] +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types 0.5.0", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation", + "core-graphics-types", + "libc", + "objc", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -359,6 +630,57 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -371,6 +693,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cssparser" version = "0.27.2" @@ -381,7 +713,7 @@ dependencies = [ "dtoa-short", "itoa 0.4.8", "matches", - "phf", + "phf 0.8.0", "proc-macro2", "quote", "smallvec", @@ -458,6 +790,16 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dioxus" version = "0.5.6" @@ -467,6 +809,7 @@ dependencies = [ "dioxus-config-macro", "dioxus-core", "dioxus-core-macro", + "dioxus-desktop", "dioxus-fullstack", "dioxus-hooks", "dioxus-hot-reload", @@ -537,6 +880,45 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ea539174bb236e0e7dc9c12b19b88eae3cb574dedbd0252a2d43ea7e6de13e2" +[[package]] +name = "dioxus-desktop" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2e0380cfcf44ed9310c6fd28454a7351293134d47b7e0b7baeaad5c5beded68" +dependencies = [ + "async-trait", + "cocoa", + "core-foundation", + "dioxus-cli-config", + "dioxus-core", + "dioxus-hooks", + "dioxus-hot-reload", + "dioxus-html", + "dioxus-interpreter-js", + "dunce", + "futures-channel", + "futures-util", + "generational-box", + "global-hotkey", + "infer", + "muda", + "objc", + "objc_id", + "rfd", + "rustc-hash", + "serde", + "serde_json", + "signal-hook", + "slab", + "tao", + "thiserror", + "tokio", + "tracing", + "urlencoding", + "webbrowser", + "wry", +] + [[package]] name = "dioxus-fullstack" version = "0.5.6" @@ -547,6 +929,7 @@ dependencies = [ "base64", "bytes", "ciborium", + "dioxus-desktop", "dioxus-hot-reload", "dioxus-lib", "dioxus-web", @@ -609,6 +992,7 @@ dependencies = [ "serde-value", "serde_json", "serde_repr", + "tokio", "tracing", "wasm-bindgen", "web-sys", @@ -632,6 +1016,8 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "351fad098c657d14f3ac2900362d2b86e83c22c4c620a404839e1ab628f3395b" dependencies = [ + "dioxus-core", + "dioxus-html", "js-sys", "md5", "sledgehammer_bindgen", @@ -755,6 +1141,35 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlopen2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "dtoa" version = "1.0.9" @@ -770,6 +1185,12 @@ dependencies = [ "dtoa", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "encoding_rs" version = "0.8.34" @@ -779,6 +1200,33 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "enumset" version = "1.1.3" @@ -853,12 +1301,41 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "fdeflate" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -871,7 +1348,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", ] [[package]] @@ -880,6 +1378,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -889,6 +1393,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.30" @@ -943,7 +1457,10 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ + "fastrand", "futures-core", + "futures-io", + "parking", "pin-project-lite", ] @@ -997,6 +1514,105 @@ dependencies = [ "byteorder", ] +[[package]] +name = "gdk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90fbf5c033c65d93792192a49a8efb5bb1e640c419682a58bb96f5ae77f3d4a" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2ea8a4909d530f79921290389cbd7c34cb9d623bfe970eaae65ca5f9cd9cce" +dependencies = [ + "gdk", + "gdkx11-sys", + "gio", + "glib", + "libc", + "x11", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee8f00f4ee46cad2939b8990f5c70c94ff882c3028f3cc5abf950fa4ab53043" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + [[package]] name = "generational-box" version = "0.5.6" @@ -1006,6 +1622,16 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -1034,6 +1660,102 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.6.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "global-hotkey" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b436093d1598b05e3b7fddc097b2bad32763f53a1beb25ab6f9718c6a60acd09" +dependencies = [ + "bitflags 2.6.0", + "cocoa", + "crossbeam-channel", + "keyboard-types", + "objc", + "once_cell", + "thiserror", + "windows-sys 0.52.0", + "x11-dl", +] + [[package]] name = "gloo" version = "0.8.1" @@ -1246,6 +1968,69 @@ dependencies = [ "web-sys", ] +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "h2" version = "0.3.26" @@ -1258,7 +2043,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.5.0", "slab", "tokio", "tokio-util", @@ -1275,6 +2060,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.13.2" @@ -1294,6 +2085,36 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "home" version = "0.5.9" @@ -1312,6 +2133,20 @@ dependencies = [ "lol_html", ] +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "http" version = "0.2.12" @@ -1410,6 +2245,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.5.0" @@ -1429,6 +2274,15 @@ dependencies = [ "cfb", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "internment" version = "0.7.5" @@ -1483,6 +2337,51 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "js-sys" version = "0.3.70" @@ -1516,6 +2415,19 @@ dependencies = [ "semver", ] +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever", + "indexmap 1.9.3", + "matches", + "selectors", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1534,6 +2446,25 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libxdo" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db" +dependencies = [ + "libxdo-sys", +] + +[[package]] +name = "libxdo-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" +dependencies = [ + "libc", + "x11", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -1599,6 +2530,21 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "manganis" version = "0.2.2" @@ -1621,7 +2567,7 @@ dependencies = [ "infer", "reqwest", "serde", - "toml", + "toml 0.7.8", "tracing", "url", ] @@ -1650,6 +2596,20 @@ dependencies = [ "regex", ] +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "matches" version = "0.1.10" @@ -1668,6 +2628,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "merge-io" version = "0.3.0" @@ -1683,6 +2652,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1698,6 +2677,16 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" version = "0.8.11" @@ -1709,6 +2698,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "muda" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453" +dependencies = [ + "cocoa", + "crossbeam-channel", + "gtk", + "keyboard-types", + "libxdo", + "objc", + "once_cell", + "png", + "thiserror", + "windows-sys 0.52.0", +] + [[package]] name = "mumble-protocol-2x" version = "0.5.0" @@ -1771,6 +2778,54 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags 1.3.2", + "jni-sys", + "ndk-sys", + "num_enum", + "raw-window-handle 0.5.2", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", + "memoffset", +] + [[package]] name = "nodrop" version = "0.1.14" @@ -1836,6 +2891,76 @@ dependencies = [ "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]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "object" version = "0.36.1" @@ -1868,7 +2993,7 @@ checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.6.0", "cfg-if", - "foreign-types", + "foreign-types 0.3.2", "libc", "once_cell", "openssl-macros", @@ -1913,13 +3038,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "ordermap" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31f2bd7b03bf2c767e1bb7b91505dbe022833776e60480275e6f2fb0db0c7503" dependencies = [ - "indexmap", + "indexmap 2.5.0", ] [[package]] @@ -1928,6 +3063,31 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "parking" version = "2.2.0" @@ -1970,7 +3130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 2.5.0", ] [[package]] @@ -1980,18 +3140,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ "phf_macros", - "phf_shared", + "phf_shared 0.8.0", "proc-macro-hack", ] +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + [[package]] name = "phf_codegen" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", ] [[package]] @@ -2000,18 +3179,28 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" dependencies = [ - "phf_shared", + "phf_shared 0.8.0", "rand 0.7.3", ] +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + [[package]] name = "phf_macros" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.8.0", + "phf_shared 0.8.0", "proc-macro-hack", "proc-macro2", "quote", @@ -2027,6 +3216,15 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -2082,6 +3280,40 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "png" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.0", +] + +[[package]] +name = "polling" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -2107,6 +3339,58 @@ dependencies = [ "syn 2.0.68", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +dependencies = [ + "toml_edit 0.20.7", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -2237,6 +3521,18 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "redox_syscall" version = "0.5.2" @@ -2295,6 +3591,7 @@ dependencies = [ "js-sys", "log", "mime", + "mime_guess", "native-tls", "once_cell", "percent-encoding", @@ -2307,14 +3604,39 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "winreg", ] +[[package]] +name = "rfd" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" +dependencies = [ + "ashpd", + "block", + "dispatch", + "js-sys", + "log", + "objc", + "objc-foundation", + "objc_id", + "pollster", + "raw-window-handle 0.6.2", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rsass" version = "0.28.10" @@ -2381,6 +3703,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.23" @@ -2431,8 +3762,8 @@ dependencies = [ "fxhash", "log", "matches", - "phf", - "phf_codegen", + "phf 0.8.0", + "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", @@ -2577,6 +3908,7 @@ dependencies = [ "http 1.1.0", "js-sys", "once_cell", + "reqwest", "send_wrapper", "serde", "serde_json", @@ -2625,6 +3957,28 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2634,6 +3988,31 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "siphasher" version = "0.3.11" @@ -2730,6 +4109,32 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "spinning" version = "0.1.0" @@ -2745,6 +4150,38 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + [[package]] name = "syn" version = "1.0.109" @@ -2794,6 +4231,74 @@ dependencies = [ "libc", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml 0.8.15", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ebbccb78deb5a36744c079eea2981b4a48ecbbe6b1b2ffbaa528bea3f5e5db" +dependencies = [ + "bitflags 1.3.2", + "cocoa", + "core-foundation", + "core-graphics", + "crossbeam-channel", + "dispatch", + "dlopen2", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "instant", + "jni", + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "scopeguard", + "tao-macros", + "unicode-segmentation", + "url", + "windows 0.54.0", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "tempfile" version = "3.10.1" @@ -2806,6 +4311,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "thin-slice" version = "0.1.1" @@ -2873,11 +4389,24 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", "pin-project-lite", "socket2", + "tokio-macros", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -2910,7 +4439,19 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.16", ] [[package]] @@ -2928,11 +4469,46 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.5.0", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.5.0", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.5.0", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +dependencies = [ + "indexmap 2.5.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.20", ] [[package]] @@ -3004,6 +4580,29 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + +[[package]] +name = "unicase" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -3055,6 +4654,12 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "uuid" version = "1.9.1" @@ -3073,12 +4678,28 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -3190,6 +4811,103 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" +dependencies = [ + "core-foundation", + "home", + "jni", + "log", + "ndk-context", + "objc", + "raw-window-handle 0.5.2", + "url", + "web-sys", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + +[[package]] +name = "webview2-com" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ae9c7e420783826cf769d2c06ac9ba462f450eca5893bb8c6c6529a4e5dd33" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows 0.52.0", + "windows-core 0.52.0", + "windows-implement 0.52.0", + "windows-interface 0.52.0", +] + +[[package]] +name = "webview2-com-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "webview2-com-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ad85fceee6c42fa3d61239eba5a11401bf38407a849ed5ea1b407df08cca72" +dependencies = [ + "thiserror", + "windows 0.52.0", + "windows-core 0.52.0", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3206,12 +4924,126 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-implement 0.52.0", + "windows-interface 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-implement 0.53.0", + "windows-interface 0.53.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-implement" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-implement" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-interface" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-interface" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3230,6 +5062,21 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3261,6 +5108,21 @@ dependencies = [ "windows_x86_64_msvc 0.52.5", ] +[[package]] +name = "windows-version" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998aa457c9ba8ff2fb9f13e9d2a930dabcea28f1d0ab94d687d8b3654844515" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3273,6 +5135,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3285,6 +5153,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3303,6 +5177,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3315,6 +5195,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3327,6 +5213,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3339,6 +5231,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3360,6 +5258,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" @@ -3370,12 +5277,150 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wry" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b717040ba9771fd88eb428c6ea6b555f8e734ff8534f02c13e8f10d97f5935e" +dependencies = [ + "base64", + "block", + "cfg_aliases 0.1.1", + "cocoa", + "core-graphics", + "crossbeam-channel", + "dunce", + "gdkx11", + "gtk", + "html5ever", + "http 0.2.12", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "objc_id", + "once_cell", + "percent-encoding", + "raw-window-handle 0.6.2", + "serde", + "serde_json", + "sha2", + "soup3", + "tao-macros", + "thiserror", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows 0.52.0", + "windows-implement 0.52.0", + "windows-version", + "x11-dl", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "xdg-home" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "xxhash-rust" version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927da81e25be1e1a2901d59b81b37dd2efd1fc9c9345a55007f09bf5a2d3ee03" +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.68", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -3396,3 +5441,41 @@ dependencies = [ "quote", "syn 2.0.68", ] + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.68", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] diff --git a/Cargo.toml b/Cargo.toml index f35fb7c..0e41232 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,22 +4,22 @@ version = "0.1.0" edition = "2021" [dependencies] -dioxus = { version = "0.5.6", features = ["web"] } -dioxus-web = "0.5.6" +dioxus = { version = "0.5.6" } +dioxus-web = { version="0.5.6", optional = true } manganis = "0.2.2" once_cell = "1.19.0" asynchronous-codec = "0.6.2" futures = "0.3.30" merge-io = "0.3.0" mumble-protocol = { version = "0.5.0", package = "mumble-protocol-2x", default-features = false, features = ["asynchronous-codec"]} -serde-wasm-bindgen = "0.6.5" serde_json = "1.0.117" tokio-util = { version = "0.7.11", features = ["codec"]} -wasm-bindgen = "0.2.92" -wasm-bindgen-futures = "0.4.42" -wasm-streams = "0.4.0" -js-sys = "0.3.70" -web-sys = { version = "0.3.70", features = ["WebTransport", "console", "WebTransportOptions", "WebTransportBidirectionalStream", "WebTransportSendStream", "WebTransportReceiveStream", "Navigator", "MediaDevices", "AudioDecoder", "AudioDecoderInit", "AudioData", "AudioEncoderConfig", "AudioDecoderConfig", "EncodedAudioChunk", "EncodedAudioChunkInit", "EncodedAudioChunkType", "CodecState", "MediaStreamTrackGenerator", "MediaStreamTrackGeneratorInit", "AudioContext", "AudioContextOptions", "MediaStream", "GainNode", "MediaStreamAudioSourceNode", "BaseAudioContext", "AudioDestinationNode", "AudioWorkletNode", "AudioWorklet", "AudioWorkletProcessor", "MediaStreamConstraints", "WorkletOptions", "AudioEncoder", "AudioEncoderInit", "AudioDataInit", "HtmlAnchorElement", "Url", "Blob", "AudioDataCopyToOptions", "AudioSampleFormat"] } +wasm-bindgen = { version = "0.2.92", optional = true } +wasm-bindgen-futures = { version = "0.4.42", optional = true } +wasm-streams = { version = "0.4.0", optional = true } +serde-wasm-bindgen = { version = "0.6.5", optional = true } +js-sys = { version = "0.3.70", optional = true } +web-sys = { version = "0.3.70", features = ["WebTransport", "console", "WebTransportOptions", "WebTransportBidirectionalStream", "WebTransportSendStream", "WebTransportReceiveStream", "Navigator", "MediaDevices", "AudioDecoder", "AudioDecoderInit", "AudioData", "AudioEncoderConfig", "AudioDecoderConfig", "EncodedAudioChunk", "EncodedAudioChunkInit", "EncodedAudioChunkType", "CodecState", "MediaStreamTrackGenerator", "MediaStreamTrackGeneratorInit", "AudioContext", "AudioContextOptions", "MediaStream", "GainNode", "MediaStreamAudioSourceNode", "BaseAudioContext", "AudioDestinationNode", "AudioWorkletNode", "AudioWorklet", "AudioWorkletProcessor", "MediaStreamConstraints", "WorkletOptions", "AudioEncoder", "AudioEncoderInit", "AudioDataInit", "HtmlAnchorElement", "Url", "Blob", "AudioDataCopyToOptions", "AudioSampleFormat"], optional = true } anyhow = "1.0.86" byteorder = "1.5.0" ogg = "0.9.1" @@ -29,3 +29,8 @@ markdown = "0.3.0" gloo-timers = { version = "0.3.0", features = ["futures"] } futures-channel = "0.3.30" sir = { version = "0.5.0", features = ["dioxus"] } + +[features] +default = ["web"] +web = ["dioxus/web", "dioxus-web", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "serde-wasm-bindgen", "js-sys", "web-sys"] +desktop = ["dioxus/desktop"] diff --git a/src/imp/desktop.rs b/src/imp/desktop.rs new file mode 100644 index 0000000..7d75e97 --- /dev/null +++ b/src/imp/desktop.rs @@ -0,0 +1,6 @@ +pub async fn network_connect( + address: String, + username: String, + event_rx: &mut UnboundedReceiver, +) -> Result<(), JsValue> { +} diff --git a/src/imp/web.rs b/src/imp/web.rs new file mode 100644 index 0000000..bb5077e --- /dev/null +++ b/src/imp/web.rs @@ -0,0 +1,488 @@ +use crate::app::ChannelId; +use crate::app::Chat; +use crate::app::Command; +use crate::app::ConnectionState; +use crate::app::STATE; +use crate::bail; +use dioxus::prelude::*; +use futures::select; +use futures::FutureExt; +use futures::SinkExt; +use futures::StreamExt; +use futures_channel::mpsc::UnboundedSender; +use gloo_timers::future::TimeoutFuture; +use manganis::{file, mg}; +use markdown; +use mumble_protocol::control::ControlPacket; +use mumble_protocol::control::{msgs, ClientControlCodec}; +use mumble_protocol::voice::VoicePacket; +use mumble_protocol::voice::VoicePacketPayload; +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::fmt; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::spawn_local as spawn; +use wasm_bindgen_futures::{future_to_promise, JsFuture}; +use web_sys::console; +use web_sys::js_sys::Promise; +use web_sys::js_sys::Reflect; +use web_sys::js_sys::Uint8Array; +use web_sys::window; +use web_sys::AudioContextOptions; +use web_sys::AudioData; +use web_sys::AudioDecoder; +use web_sys::AudioDecoderConfig; +use web_sys::AudioDecoderInit; +use web_sys::AudioEncoder; +use web_sys::AudioEncoderConfig; +use web_sys::AudioEncoderInit; +use web_sys::AudioWorkletNode; +use web_sys::EncodedAudioChunk; +use web_sys::EncodedAudioChunkInit; +use web_sys::EncodedAudioChunkType; +use web_sys::MediaStream; +use web_sys::MediaStreamConstraints; +use web_sys::MediaStreamTrackGenerator; +use web_sys::MediaStreamTrackGeneratorInit; +use web_sys::MessageEvent; +use web_sys::WebTransport; +use web_sys::WebTransportBidirectionalStream; +use web_sys::WebTransportOptions; +use web_sys::WorkletOptions; + +pub use web_sys::AudioContext; + +pub struct AudioPlayer(AudioDecoder); + +impl AudioPlayer { + pub fn play_opus(&mut self, payload: &[u8]) { + let js_audio_payload = Uint8Array::from(payload); + let _ = self.0.decode( + &EncodedAudioChunk::new(&EncodedAudioChunkInit::new( + &js_audio_payload.into(), + 0.0, + EncodedAudioChunkType::Key, + )) + .unwrap(), + ); + } +} + +pub struct Error(JsValue); + +impl From for Error { + fn from(value: anyhow::Error) -> Self { + Error(JsError::new(&value.to_string()).into()) + } +} + +impl From for Error { + fn from(value: JsValue) -> Self { + Error(value) + } +} + +impl From for Error { + fn from(value: JsError) -> Self { + Error(JsError::from(value).into()) + } +} + +impl Error { + pub fn new(text: String) -> Self { + wasm_bindgen::JsError::new(&text).into() + } + + pub fn log(&self) { + console::error_1(&self.0); + } +} + +impl std::error::Error for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let text: String = js_sys::Object::from(self.0.clone()).to_string().into(); + f.write_str(&text) + } +} + +impl fmt::Debug for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let text: String = js_sys::Object::from(self.0.clone()).to_string().into(); + f.write_str(&text) + } +} + +// Borrowed from +// https://github.com/security-union/videocall-rs/blob/main/videocall-client/src/decode/config.rs#L6 +fn configure_audio_context() -> AudioContext { + let mut audio_context_options = AudioContextOptions::new(); + audio_context_options.sample_rate(48000 as f32); + let audio_context = AudioContext::new_with_context_options(&audio_context_options).unwrap(); + audio_context +} + +trait PromiseExt { + fn into_future(self) -> JsFuture; +} + +impl PromiseExt for Promise { + fn into_future(self) -> JsFuture { + self.into() + } +} + +async fn create_encoder_worklet( + audio_context: &AudioContext, + packets: UnboundedSender>, +) -> Result { + let stream = window() + .unwrap() + .navigator() + .media_devices()? + .get_user_media_with_constraints(MediaStreamConstraints::new().audio(&JsValue::TRUE))? + .into_future() + .await? + .dyn_into() + .map_err(|e| JsError::new(&format!("not a stream: {e:?}")))?; + + let options = WorkletOptions::new(); + Reflect::set( + &options, + &"processorOptions".into(), + &wasm_bindgen::module(), + )?; + + let module = "rust_mic_worklet.js"; + console::log_1(&format!("Loading mic worklet from {module:?}").into()); + audio_context + .audio_worklet()? + .add_module_with_options(module, &options)? + .into_future() + .await?; + + let source = audio_context.create_media_stream_source(&stream)?; + let worklet_node = AudioWorkletNode::new(audio_context, "rust_mic_worklet")?; + + let error: Closure = Closure::new(|e| console::error_1(&e)); + + let mut download_buffer = std::cell::RefCell::new(Vec::new()); + + // This knows what MediaStreamTrackGenerator to use as it closes around it + let mut sequence_num = 0; + let output: Closure = + Closure::new(move |audio_data: EncodedAudioChunk| { + let mut array = vec![0u8; audio_data.byte_length() as usize]; + audio_data.copy_to_with_u8_array(&mut array); + + download_buffer.borrow_mut().push(array.clone()); + if download_buffer.borrow().len() > 200 { + //download_data(download_buffer.borrow().to_vec(), "download_buffer.opus"); + //download_data( + // ass::encode(download_buffer.borrow().to_vec(), 960, 0), + // "download_buffer.opus", + //); + download_buffer.borrow_mut().clear(); + } + + let _ = + packets.unbounded_send(ControlPacket::UDPTunnel(Box::new(VoicePacket::Audio { + _dst: std::marker::PhantomData, + target: 0, + session_id: (), + seq_num: sequence_num, + payload: VoicePacketPayload::Opus(array.into(), false), + position_info: None, + }))); + sequence_num = sequence_num.wrapping_add(2); + }); + + let audio_encoder = AudioEncoder::new(&AudioEncoderInit::new( + error.as_ref().unchecked_ref(), + output.as_ref().unchecked_ref(), + )) + .unwrap(); + + // This is required to prevent these from being deallocated + error.forget(); + output.forget(); + let encoder_config = AudioEncoderConfig::new("opus"); + encoder_config.set_number_of_channels(1); + encoder_config.set_sample_rate(48000); + encoder_config.set_bitrate(72_000.0); + + audio_encoder.configure(&encoder_config); + console::log_1(&"Created Audio Encoder".into()); + + let mut download_buffer = std::cell::RefCell::new(Vec::new()); + + let onmessage: Closure = Closure::new(move |event: MessageEvent| { + match AudioData::new(event.data().unchecked_ref()) { + Ok(data) => { + let x = web_sys::AudioDataCopyToOptions::new(0); + x.set_format(web_sys::AudioSampleFormat::F32); + let mut sub_buffer = vec![0; data.allocation_size(&x).unwrap() as usize]; + data.copy_to_with_u8_array(&mut sub_buffer, &x); + download_buffer.borrow_mut().append(&mut sub_buffer); + if download_buffer.borrow().len() > 48000 * 10 * 4 { + //pub fn download_data(data: Vec, filename: &str) -> Result<(), JsValue> { + //download_data(download_buffer.borrow().to_vec(), "download_buffer.pcm32"); + download_buffer.borrow_mut().clear(); + } + + audio_encoder.encode(&data); + } + Err(err) => { + console::error_1(&err); + console::debug_1(&event); + } + } + }); + Reflect::set( + &Reflect::get(&worklet_node, &"port".into())?, + &"onmessage".into(), + onmessage.as_ref(), + )?; + onmessage.forget(); + + source.connect_with_audio_node(&worklet_node)?; + worklet_node.connect_with_audio_node(&audio_context.destination())?; + + Ok(worklet_node) +} + +pub fn create_player(audio_context: &AudioContext) -> Result { + 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); + + // 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); + + 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( + address: String, + username: String, + event_rx: &mut UnboundedReceiver, +) -> Result<(), Error> { + *STATE.server.write() = Default::default(); + *STATE.status.write() = ConnectionState::Connecting; + + console::log_1(&"Rust via WASM!".into()); + + let Ok(server_hash): Result, _> = include_str!("../../server_hash.txt") + .trim() + .trim_matches(&['[', ']']) + .split(',') + .map(|x| x.trim().parse()) + .collect() + else { + bail!("could not parse server hash"); + }; + let hash = web_sys::js_sys::Uint8Array::from(server_hash.as_slice()); + + let object = web_sys::js_sys::Object::new(); + + Reflect::set( + &object, + &JsValue::from_str("algorithm"), + &JsValue::from_str("sha-256"), + )?; + + web_sys::js_sys::Reflect::set(&object, &"value".into(), &hash)?; + + let array = web_sys::js_sys::Array::new(); + array.push(&object); + + console::log_1(&object.clone().into()); + console::log_1(&"Created option object!".into()); + + let mut options = WebTransportOptions::new(); + options.server_certificate_hashes(&array); + + console::log_1(&"Created WebTransportOptions!".into()); + + let transport = WebTransport::new_with_options(&address, &options)?; + console::log_1(&"Created WebTransport connection object.".into()); + console::log_1(&transport.clone().into()); + + if let Err(e) = wasm_bindgen_futures::JsFuture::from(transport.ready()).await { + bail!("could not connect to transport: {e:?}"); + } + + console::log_1(&"Transport is ready.".into()); + + let stream: WebTransportBidirectionalStream = + wasm_bindgen_futures::JsFuture::from(transport.create_bidirectional_stream()) + .await? + .into(); + + let wasm_stream_readable = wasm_streams::ReadableStream::from_raw(stream.readable().into()); + let wasm_stream_writable = wasm_streams::WritableStream::from_raw(stream.writable().into()); + + let read_codec = ClientControlCodec::new(); + let write_codec = ClientControlCodec::new(); + + let mut reader = + asynchronous_codec::FramedRead::new(wasm_stream_readable.into_async_read(), read_codec); + let mut writer = + asynchronous_codec::FramedWrite::new(wasm_stream_writable.into_async_write(), write_codec); + + let (mut send_chan, mut writer_recv_chan) = futures_channel::mpsc::unbounded(); + + // 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(); + *STATE.status.write() = ConnectionState::Disconnected; + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 4dead63..dc9451d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,16 @@ -pub mod app; - use app::ChannelId; use app::Chat; use app::Command; use app::ConnectionState; -use dioxus::prelude::*; - use app::STATE; +use dioxus::prelude::*; use futures::select; use futures::FutureExt; use futures::SinkExt; use futures::StreamExt; use futures_channel::mpsc::UnboundedSender; use gloo_timers::future::TimeoutFuture; +pub use imp::Error; use manganis::{file, mg}; use markdown; use mumble_protocol::control::ControlPacket; @@ -22,324 +20,24 @@ use mumble_protocol::voice::VoicePacketPayload; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::fmt; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::spawn_local as spawn; -use wasm_bindgen_futures::{future_to_promise, JsFuture}; -use web_sys::console; -use web_sys::js_sys::Promise; -use web_sys::js_sys::Reflect; -use web_sys::js_sys::Uint8Array; -use web_sys::window; -use web_sys::AudioContext; -use web_sys::AudioContextOptions; -use web_sys::AudioData; -use web_sys::AudioDecoder; -use web_sys::AudioDecoderConfig; -use web_sys::AudioDecoderInit; -use web_sys::AudioEncoder; -use web_sys::AudioEncoderConfig; -use web_sys::AudioEncoderInit; -use web_sys::AudioWorkletNode; -use web_sys::EncodedAudioChunk; -use web_sys::EncodedAudioChunkInit; -use web_sys::EncodedAudioChunkType; -use web_sys::MediaStream; -use web_sys::MediaStreamConstraints; -use web_sys::MediaStreamTrackGenerator; -use web_sys::MediaStreamTrackGeneratorInit; -use web_sys::MessageEvent; -use web_sys::WebTransport; -use web_sys::WebTransportBidirectionalStream; -use web_sys::WebTransportOptions; -use web_sys::WorkletOptions; -mod ass { - use byteorder::{ByteOrder, LittleEndian}; - use ogg::PacketWriter; +pub mod app; - const VER: &str = "ballz"; +#[cfg(feature = "web")] +#[path = "imp/web.rs"] +pub mod imp; - const fn to_samples(ms: u32) -> usize { - ((S_PS * ms) / 1000) as usize - } +/* +#[cfg(feature = "desktop")] +#[path = "imp/desktop.rs"] +pub mod imp; +*/ - const fn calc_sr_u64(val: u64, from: u32, to: u32) -> u64 { - (val * to as u64) / from as u64 - } - - pub fn encode(pre_encoded_frames: Vec>, frame_size: usize, skip: u16) -> Vec { - let mut buffer: Vec = Vec::new(); - let mut packet_writer = PacketWriter::new(&mut buffer); - - // Hardcoded serial number - let serial = 12345; - - let skip_48 = calc_sr_u64(skip.into(), 48000, 48000); - - let opus_head: [u8; 19] = [ - b'O', b'p', b'u', b's', b'H', b'e', b'a', b'd', 1, 1, // NUM_CHANNELS = 1 - 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - - let mut head = opus_head; - LittleEndian::write_u16(&mut head[10..12], skip_48 as u16); - LittleEndian::write_u32(&mut head[12..16], 48000); - - let mut opus_tags: Vec = Vec::with_capacity(60); - let vendor_str = format!("ogg-opus {}", VER); - opus_tags.extend(b"OpusTags"); - let mut len_bf = [0u8; 4]; - LittleEndian::write_u32(&mut len_bf, vendor_str.len() as u32); - opus_tags.extend(&len_bf); - opus_tags.extend(vendor_str.bytes()); - opus_tags.extend(&[0u8; 4]); - - let _ = packet_writer.write_packet(&head, serial, ogg::PacketWriteEndInfo::EndPage, 0); - let _ = packet_writer.write_packet(&opus_tags, serial, ogg::PacketWriteEndInfo::EndPage, 0); - - for (i, frame) in pre_encoded_frames.iter().enumerate() { - let is_last = i == pre_encoded_frames.len() - 1; - //let granule_pos = 0; - let granule_pos = - calc_sr_u64((skip as usize + (i + 1) * frame_size) as u64, 48000, 48000); - - let _ = packet_writer.write_packet( - frame.clone(), - serial, - if is_last { - ogg::PacketWriteEndInfo::EndStream - } else { - ogg::PacketWriteEndInfo::NormalPacket - }, - granule_pos, - ); - } - - buffer - } -} - -// Function to download data as a file -pub fn download_data(data: Vec, filename: &str) -> Result<(), JsValue> { - use wasm_bindgen::prelude::*; - use web_sys::{window, Blob, HtmlAnchorElement, Url}; - // Create a new Blob from the data - let array = web_sys::js_sys::Uint8Array::from(&data[..]); - let blob = Blob::new_with_u8_array_sequence(&vec![array].into())?; - - // Create a URL for the Blob - let url = Url::create_object_url_with_blob(&blob)?; - - // Create an anchor element and set its href to the Blob URL - let document = window().unwrap().document().unwrap(); - let a = document - .create_element("a")? - .dyn_into::()?; - a.set_href(&url); - a.set_download(filename); - - // Append the anchor to the document body, click it, and remove it - document.body().unwrap().append_child(&a)?; - a.click(); - document.body().unwrap().remove_child(&a)?; - - // Revoke the object URL to free resources - Url::revoke_object_url(&url)?; - - Ok(()) -} - -// Borrowed from -// https://github.com/security-union/videocall-rs/blob/main/videocall-client/src/decode/config.rs#L6 -fn configure_audio_context() -> AudioContext { - let mut audio_context_options = AudioContextOptions::new(); - audio_context_options.sample_rate(48000 as f32); - let audio_context = AudioContext::new_with_context_options(&audio_context_options).unwrap(); - audio_context -} - -trait PromiseExt { - fn into_future(self) -> JsFuture; -} - -impl PromiseExt for Promise { - fn into_future(self) -> JsFuture { - self.into() - } -} - -async fn create_encoder_worklet( - audio_context: &AudioContext, - packets: UnboundedSender>, -) -> Result { - let stream = window() - .unwrap() - .navigator() - .media_devices()? - .get_user_media_with_constraints(MediaStreamConstraints::new().audio(&JsValue::TRUE))? - .into_future() - .await? - .dyn_into() - .map_err(|e| JsError::new(&format!("not a stream: {e:?}")))?; - - let options = WorkletOptions::new(); - Reflect::set( - &options, - &"processorOptions".into(), - &wasm_bindgen::module(), - )?; - - let module = "rust_mic_worklet.js"; - console::log_1(&format!("Loading mic worklet from {module:?}").into()); - audio_context - .audio_worklet()? - .add_module_with_options(module, &options)? - .into_future() - .await?; - - let source = audio_context.create_media_stream_source(&stream)?; - let worklet_node = AudioWorkletNode::new(audio_context, "rust_mic_worklet")?; - - let error: Closure = Closure::new(|e| console::error_1(&e)); - - let mut download_buffer = std::cell::RefCell::new(Vec::new()); - - // This knows what MediaStreamTrackGenerator to use as it closes around it - let mut sequence_num = 0; - let output: Closure = - Closure::new(move |audio_data: EncodedAudioChunk| { - let mut array = vec![0u8; audio_data.byte_length() as usize]; - audio_data.copy_to_with_u8_array(&mut array); - - download_buffer.borrow_mut().push(array.clone()); - if download_buffer.borrow().len() > 200 { - //download_data(download_buffer.borrow().to_vec(), "download_buffer.opus"); - //download_data( - // ass::encode(download_buffer.borrow().to_vec(), 960, 0), - // "download_buffer.opus", - //); - download_buffer.borrow_mut().clear(); - } - - let _ = - packets.unbounded_send(ControlPacket::UDPTunnel(Box::new(VoicePacket::Audio { - _dst: std::marker::PhantomData, - target: 0, - session_id: (), - seq_num: sequence_num, - payload: VoicePacketPayload::Opus(array.into(), false), - position_info: None, - }))); - sequence_num = sequence_num.wrapping_add(2); - }); - - let audio_encoder = AudioEncoder::new(&AudioEncoderInit::new( - error.as_ref().unchecked_ref(), - output.as_ref().unchecked_ref(), - )) - .unwrap(); - - // This is required to prevent these from being deallocated - error.forget(); - output.forget(); - let encoder_config = AudioEncoderConfig::new("opus"); - encoder_config.set_number_of_channels(1); - encoder_config.set_sample_rate(48000); - encoder_config.set_bitrate(72_000.0); - - audio_encoder.configure(&encoder_config); - console::log_1(&"Created Audio Encoder".into()); - - let mut download_buffer = std::cell::RefCell::new(Vec::new()); - - let onmessage: Closure = Closure::new(move |event: MessageEvent| { - match AudioData::new(event.data().unchecked_ref()) { - Ok(data) => { - let x = web_sys::AudioDataCopyToOptions::new(0); - x.set_format(web_sys::AudioSampleFormat::F32); - let mut sub_buffer = vec![0; data.allocation_size(&x).unwrap() as usize]; - data.copy_to_with_u8_array(&mut sub_buffer, &x); - download_buffer.borrow_mut().append(&mut sub_buffer); - if download_buffer.borrow().len() > 48000 * 10 * 4 { - //pub fn download_data(data: Vec, filename: &str) -> Result<(), JsValue> { - //download_data(download_buffer.borrow().to_vec(), "download_buffer.pcm32"); - download_buffer.borrow_mut().clear(); - } - - audio_encoder.encode(&data); - } - Err(err) => { - console::error_1(&err); - console::debug_1(&event); - } - } - }); - Reflect::set( - &Reflect::get(&worklet_node, &"port".into())?, - &"onmessage".into(), - onmessage.as_ref(), - )?; - onmessage.forget(); - - source.connect_with_audio_node(&worklet_node)?; - worklet_node.connect_with_audio_node(&audio_context.destination())?; - - Ok(worklet_node) -} - -fn create_decoder(audio_context: &AudioContext) -> Result { - 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); - - // 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); - - 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(audio_decoder) +#[macro_export] +macro_rules! bail { + ($($x:tt)*) => { + return Err(crate::Error::new(format!($($x)*))) + }; } pub async fn network_entrypoint(mut event_rx: UnboundedReceiver) { @@ -353,201 +51,17 @@ pub async fn network_entrypoint(mut event_rx: UnboundedReceiver) { panic!("Did not receive connect command") }; - if let Err(error) = network_connect(address, username, &mut event_rx).await { - console::error_1(&error); - let text = js_sys::Object::from(error).to_string().into(); - *STATE.status.write() = ConnectionState::Failed(text); + if let Err(error) = imp::network_connect(address, username, &mut event_rx).await { + error.log(); + *STATE.status.write() = ConnectionState::Failed(error.to_string()); } } } -macro_rules! bail { - ($($x:tt)*) => { - return Err(wasm_bindgen::JsError::new(&format!($($x)*)).into()) - }; -} - -async fn network_connect( - address: String, - username: String, - event_rx: &mut UnboundedReceiver, -) -> Result<(), JsValue> { - *STATE.server.write() = Default::default(); - *STATE.status.write() = ConnectionState::Connecting; - - console::log_1(&"Rust via WASM!".into()); - - let Ok(server_hash): Result, _> = include_str!("../server_hash.txt") - .trim() - .trim_matches(&['[', ']']) - .split(',') - .map(|x| x.trim().parse()) - .collect() - else { - bail!("could not parse server hash"); - }; - let hash = web_sys::js_sys::Uint8Array::from(server_hash.as_slice()); - - let object = web_sys::js_sys::Object::new(); - - Reflect::set( - &object, - &JsValue::from_str("algorithm"), - &JsValue::from_str("sha-256"), - )?; - - web_sys::js_sys::Reflect::set(&object, &"value".into(), &hash)?; - - let array = web_sys::js_sys::Array::new(); - array.push(&object); - - console::log_1(&object.clone().into()); - console::log_1(&"Created option object!".into()); - - let mut options = WebTransportOptions::new(); - options.server_certificate_hashes(&array); - - console::log_1(&"Created WebTransportOptions!".into()); - - let transport = WebTransport::new_with_options(&address, &options)?; - console::log_1(&"Created WebTransport connection object.".into()); - console::log_1(&transport.clone().into()); - - if let Err(e) = wasm_bindgen_futures::JsFuture::from(transport.ready()).await { - bail!("could not connect to transport: {e:?}"); - } - - console::log_1(&"Transport is ready.".into()); - - let stream: WebTransportBidirectionalStream = - wasm_bindgen_futures::JsFuture::from(transport.create_bidirectional_stream()) - .await? - .into(); - - let wasm_stream_readable = wasm_streams::ReadableStream::from_raw(stream.readable().into()); - let wasm_stream_writable = wasm_streams::WritableStream::from_raw(stream.writable().into()); - - let read_codec = ClientControlCodec::new(); - let write_codec = ClientControlCodec::new(); - - let mut reader = - asynchronous_codec::FramedRead::new(wasm_stream_readable.into_async_read(), read_codec); - let mut writer = - asynchronous_codec::FramedWrite::new(wasm_stream_writable.into_async_write(), write_codec); - - let (mut send_chan, mut writer_recv_chan) = futures_channel::mpsc::unbounded(); - - // 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) => console::error_1(&err), - } - }); - - // 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)) => { - let res =accept_packet(msg, &audio_context, &mut decoder_map); - if let Err(err) = res { - console::error_1(&err.into()); - } - }, - 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 = accept_command(command, &mut send_chan); - if let Err(err) = res { - console::error_1(&err.into()); - } - } - None => continue, - } - } - } - } - let _ = send_chan.close(); - *STATE.status.write() = ConnectionState::Disconnected; - Ok(()) -} - fn accept_command( command: Command, send_chan: &mut UnboundedSender>, -) -> Result<(), JsValue> { +) -> Result<(), Error> { match command { Command::SendChat { markdown, channels } => { use markdown::*; @@ -591,12 +105,9 @@ fn accept_command( fn accept_packet( msg: ControlPacket, - audio_context: &AudioContext, - decoder_map: &mut HashMap, -) -> Result<(), JsValue> { - if !matches!(msg, ControlPacket::UDPTunnel(_) | ControlPacket::Ping(_)) { - console::log_1(&format!("receiving {:#?}", msg).into()); - } + audio_context: &imp::AudioContext, + player_map: &mut HashMap, +) -> Result<(), Error> { match msg { ControlPacket::UDPTunnel(u) => { match *u.clone() { @@ -609,10 +120,10 @@ fn accept_packet( position_info, } => { // Get or create audio decoder for this user - let audio_decoder = match decoder_map.entry(session_id) { + let audio_player = match player_map.entry(session_id) { Entry::Occupied(occupied_entry) => occupied_entry.into_mut(), Entry::Vacant(vacant_entry) => { - vacant_entry.insert(create_decoder(&audio_context)?) + vacant_entry.insert(imp::create_player(&audio_context)?) } }; // This will over time (as users join and leave) leak @@ -621,15 +132,7 @@ fn accept_packet( // infra on channel join and update it as new users join the channel, dropping // any audio packets that come in the meantime. if let VoicePacketPayload::Opus(audio_payload, end_bit) = payload { - let js_audio_payload = Uint8Array::from(audio_payload.as_ref()); - let _ = audio_decoder.decode( - &EncodedAudioChunk::new(&EncodedAudioChunkInit::new( - &js_audio_payload.into(), - 0.0, - EncodedAudioChunkType::Key, - )) - .unwrap(), - ); + audio_player.play_opus(audio_payload.as_ref()); //console::log_1(&"Oueued audio chunk for decoding".into()); } }