cleanup: room & dependencies (#76)

This commit is contained in:
Théo Monnom
2023-05-25 20:13:34 +02:00
committed by GitHub
parent a9e6865137
commit 05ad1c95af
46 changed files with 1094 additions and 1031 deletions
Generated
+116 -113
View File
@@ -10,30 +10,29 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aes"
version = "0.7.5"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.70"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "autocfg"
@@ -43,9 +42,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.21.0"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
[[package]]
name = "base64ct"
@@ -70,9 +69,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.12.0"
version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "byteorder"
@@ -124,11 +123,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cipher"
version = "0.3.0"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"generic-array",
"crypto-common",
"inout",
]
[[package]]
@@ -165,9 +165,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "cpufeatures"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
dependencies = [
"libc",
]
@@ -224,7 +224,7 @@ dependencies = [
"proc-macro2",
"quote",
"scratch",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -241,7 +241,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -265,9 +265,9 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "digest"
version = "0.10.6"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
@@ -352,9 +352,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flate2"
version = "1.0.25"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -446,7 +446,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -508,9 +508,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.3.18"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
dependencies = [
"bytes",
"fnv",
@@ -658,6 +658,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]]
name = "instant"
version = "0.1.12"
@@ -669,9 +678,9 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.10"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.1",
"libc",
@@ -722,9 +731,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.61"
version = "0.3.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
dependencies = [
"wasm-bindgen",
]
@@ -749,9 +758,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.141"
version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]]
name = "link-cplusplus"
@@ -764,9 +773,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.3.2"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "livekit"
@@ -888,9 +897,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
@@ -947,17 +956,11 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openssl"
version = "0.10.50"
version = "0.10.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1"
checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56"
dependencies = [
"bitflags",
"cfg-if",
@@ -976,7 +979,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -987,9 +990,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.85"
version = "0.9.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0"
checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [
"cc",
"libc",
@@ -1073,9 +1076,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "ppv-lite86"
@@ -1095,9 +1098,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.56"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
dependencies = [
"unicode-ident",
]
@@ -1158,9 +1161,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.26"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
dependencies = [
"proc-macro2",
]
@@ -1215,9 +1218,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.7.3"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
dependencies = [
"aho-corasick",
"memchr",
@@ -1226,15 +1229,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.29"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "reqwest"
version = "0.11.16"
version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [
"base64",
"bytes",
@@ -1284,9 +1287,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.37.12"
version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "722529a737f5a942fdbac3a46cee213053196737c5eaa3386d52e85b786f2659"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [
"bitflags",
"errno",
@@ -1378,9 +1381,9 @@ dependencies = [
[[package]]
name = "security-framework"
version = "2.8.2"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
dependencies = [
"bitflags",
"core-foundation",
@@ -1391,9 +1394,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.8.0"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
dependencies = [
"core-foundation-sys",
"libc",
@@ -1401,22 +1404,22 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.160"
version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.160"
version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -1506,9 +1509,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
@@ -1523,9 +1526,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.15"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
dependencies = [
"proc-macro2",
"quote",
@@ -1582,14 +1585,14 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
name = "time"
version = "0.3.20"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
dependencies = [
"serde",
"time-core",
@@ -1597,9 +1600,9 @@ dependencies = [
[[package]]
name = "time-core"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "tinyvec"
@@ -1618,9 +1621,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.27.0"
version = "1.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
dependencies = [
"autocfg",
"bytes",
@@ -1632,18 +1635,18 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.45.0",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.0.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -1668,9 +1671,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
version = "0.1.12"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -1694,9 +1697,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.7"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [
"bytes",
"futures-core",
@@ -1726,20 +1729,20 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.23"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.16",
]
[[package]]
name = "tracing-core"
version = "0.1.30"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
dependencies = [
"once_cell",
]
@@ -1785,9 +1788,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "unicode-normalization"
@@ -1857,9 +1860,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -1867,24 +1870,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.16",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.34"
version = "0.4.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
dependencies = [
"cfg-if",
"js-sys",
@@ -1894,9 +1897,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1904,28 +1907,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.16",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
[[package]]
name = "web-sys"
version = "0.3.61"
version = "0.3.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2166,9 +2169,9 @@ dependencies = [
[[package]]
name = "zip"
version = "0.6.4"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
dependencies = [
"aes",
"byteorder",
+130 -149
View File
@@ -35,14 +35,13 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aes"
version = "0.7.5"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
@@ -183,9 +182,9 @@ dependencies = [
[[package]]
name = "base64"
version = "0.21.0"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
[[package]]
name = "base64ct"
@@ -232,9 +231,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.2.1"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813"
checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84"
[[package]]
name = "block"
@@ -272,9 +271,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.12.1"
version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "bytemuck"
@@ -293,7 +292,7 @@ checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -371,11 +370,12 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "cipher"
version = "0.3.0"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"generic-array",
"crypto-common",
"inout",
]
[[package]]
@@ -569,7 +569,7 @@ dependencies = [
"proc-macro2",
"quote",
"scratch",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -586,7 +586,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -608,35 +608,15 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "digest"
version = "0.10.6"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dispatch"
version = "0.2.0"
@@ -660,16 +640,16 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "ecolor"
version = "0.21.0"
source = "git+https://github.com/emilk/egui#e9fa6c8ff68a0257ce0f2801446ba701917b7ae9"
version = "0.22.0"
source = "git+https://github.com/emilk/egui#307565efa55158cfa6b82d2e8fdc4c4914b954ed"
dependencies = [
"bytemuck",
]
[[package]]
name = "egui"
version = "0.21.0"
source = "git+https://github.com/emilk/egui#e9fa6c8ff68a0257ce0f2801446ba701917b7ae9"
version = "0.22.0"
source = "git+https://github.com/emilk/egui#307565efa55158cfa6b82d2e8fdc4c4914b954ed"
dependencies = [
"ahash 0.8.3",
"epaint",
@@ -679,8 +659,8 @@ dependencies = [
[[package]]
name = "egui-wgpu"
version = "0.21.0"
source = "git+https://github.com/emilk/egui#e9fa6c8ff68a0257ce0f2801446ba701917b7ae9"
version = "0.22.0"
source = "git+https://github.com/emilk/egui#307565efa55158cfa6b82d2e8fdc4c4914b954ed"
dependencies = [
"bytemuck",
"epaint",
@@ -693,8 +673,8 @@ dependencies = [
[[package]]
name = "egui-winit"
version = "0.21.1"
source = "git+https://github.com/emilk/egui#e9fa6c8ff68a0257ce0f2801446ba701917b7ae9"
version = "0.22.0"
source = "git+https://github.com/emilk/egui#307565efa55158cfa6b82d2e8fdc4c4914b954ed"
dependencies = [
"arboard",
"egui",
@@ -714,8 +694,8 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "emath"
version = "0.21.0"
source = "git+https://github.com/emilk/egui#e9fa6c8ff68a0257ce0f2801446ba701917b7ae9"
version = "0.22.0"
source = "git+https://github.com/emilk/egui#307565efa55158cfa6b82d2e8fdc4c4914b954ed"
dependencies = [
"bytemuck",
]
@@ -744,8 +724,8 @@ dependencies = [
[[package]]
name = "epaint"
version = "0.21.0"
source = "git+https://github.com/emilk/egui#e9fa6c8ff68a0257ce0f2801446ba701917b7ae9"
version = "0.22.0"
source = "git+https://github.com/emilk/egui#307565efa55158cfa6b82d2e8fdc4c4914b954ed"
dependencies = [
"ab_glyph",
"ahash 0.8.3",
@@ -950,7 +930,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -1104,9 +1084,9 @@ dependencies = [
[[package]]
name = "h2"
version = "0.3.18"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
dependencies = [
"bytes",
"fnv",
@@ -1190,6 +1170,15 @@ dependencies = [
"digest",
]
[[package]]
name = "home"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "http"
version = "0.2.9"
@@ -1306,6 +1295,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]]
name = "instant"
version = "0.1.12"
@@ -1320,9 +1318,9 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.10"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.1",
"libc",
@@ -1404,9 +1402,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.61"
version = "0.3.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
dependencies = [
"wasm-bindgen",
]
@@ -1471,9 +1469,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "livekit"
@@ -1652,9 +1650,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]]
name = "naga"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00ce114f2867153c079d4489629dbd27aa4b5387a8ba5341bd3f6dfe870688f"
checksum = "94d3edd593521f4a1dfd9b25193ed0224764572905f013d30ca5fbb85e010876"
dependencies = [
"bit-set",
"bitflags 1.3.2",
@@ -1918,12 +1916,6 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openssl"
version = "0.10.52"
@@ -1947,7 +1939,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -2056,22 +2048,22 @@ dependencies = [
[[package]]
name = "pin-project"
version = "1.0.12"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.12"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.16",
]
[[package]]
@@ -2133,9 +2125,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.56"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
dependencies = [
"unicode-ident",
]
@@ -2300,22 +2292,11 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall 0.2.16",
"thiserror",
]
[[package]]
name = "regex"
version = "1.8.1"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
dependencies = [
"aho-corasick",
"memchr",
@@ -2324,9 +2305,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.7.1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "renderdoc-sys"
@@ -2336,9 +2317,9 @@ checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
[[package]]
name = "reqwest"
version = "0.11.17"
version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [
"base64",
"bytes",
@@ -2465,9 +2446,9 @@ dependencies = [
[[package]]
name = "security-framework"
version = "2.8.2"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
@@ -2478,9 +2459,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.8.0"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
dependencies = [
"core-foundation-sys",
"libc",
@@ -2488,22 +2469,22 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.162"
version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.162"
version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -2677,9 +2658,9 @@ checksum = "9df65f20698aeed245efdde3628a6b559ea1239bbb871af1b6e3b58c413b2bd1"
[[package]]
name = "subtle"
version = "2.4.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
@@ -2694,9 +2675,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.15"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
dependencies = [
"proc-macro2",
"quote",
@@ -2753,7 +2734,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -2835,9 +2816,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.28.0"
version = "1.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
dependencies = [
"autocfg",
"bytes",
@@ -2860,7 +2841,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@@ -2914,15 +2895,15 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "0.6.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
[[package]]
name = "toml_edit"
version = "0.19.8"
version = "0.19.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [
"indexmap",
"toml_datetime",
@@ -2955,14 +2936,14 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
name = "tracing-core"
version = "0.1.30"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
dependencies = [
"once_cell",
"valuable",
@@ -3048,9 +3029,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "unicode-normalization"
@@ -3142,9 +3123,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -3152,24 +3133,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.16",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.34"
version = "0.4.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
dependencies = [
"cfg-if",
"js-sys",
@@ -3179,9 +3160,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -3189,22 +3170,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.16",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.84"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
[[package]]
name = "wayland-client"
@@ -3281,9 +3262,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.61"
version = "0.3.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -3291,12 +3272,12 @@ dependencies = [
[[package]]
name = "webbrowser"
version = "0.8.9"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b692165700260bbd40fbc5ff23766c03e339fbaca907aeea5cb77bf0a553ca83"
checksum = "fd222aa310eb7532e3fd427a5d7db7e44bc0b0cf1c1e21139c345325511a85b6"
dependencies = [
"core-foundation",
"dirs",
"home",
"jni",
"log",
"ndk-context",
@@ -3329,9 +3310,9 @@ checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
name = "wgpu"
version = "0.16.0"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13edd72c7b08615b7179dd7e778ee3f0bdc870ef2de9019844ff2cceeee80b11"
checksum = "3059ea4ddec41ca14f356833e2af65e7e38c0a8f91273867ed526fb9bafcca95"
dependencies = [
"arrayvec",
"cfg-if",
@@ -3353,13 +3334,13 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "0.16.0"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625bea30a0ba50d88025f95c80211d1a85c86901423647fb74f397f614abbd9a"
checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2"
dependencies = [
"arrayvec",
"bit-vec",
"bitflags 2.2.1",
"bitflags 2.3.1",
"codespan-reporting",
"log",
"naga",
@@ -3384,7 +3365,7 @@ dependencies = [
"arrayvec",
"ash",
"bit-set",
"bitflags 2.2.1",
"bitflags 2.3.1",
"block",
"core-graphics-types",
"d3d12",
@@ -3422,7 +3403,7 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd33a976130f03dcdcd39b3810c0c3fc05daf86f0aaf867db14bfb7c4a9a32b"
dependencies = [
"bitflags 2.2.1",
"bitflags 2.3.1",
"js-sys",
"web-sys",
]
@@ -3660,9 +3641,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winit"
version = "0.28.5"
version = "0.28.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94c9651471cd576737671fbf7081edfea43de3e06846dd9bd4e49ea803c9f55f"
checksum = "866db3f712fffba75d31bf0cdecf357c8aeafd158c5b7ab51dba2a2b2d47f196"
dependencies = [
"android-activity",
"bitflags 1.3.2",
@@ -3764,15 +3745,15 @@ dependencies = [
[[package]]
name = "xml-rs"
version = "0.8.8"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f20f14e2bd1fef6ec891d50dbb37c7290a0568a6bbd9020bf62010d02b6f80e"
checksum = "2d8f380ae16a37b30e6a2cf67040608071384b1450c189e61bea3ff57cde922d"
[[package]]
name = "zip"
version = "0.6.5"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e92305c174683d78035cbf1b70e18db6329cc0f1b9cae0a52ca90bf5bfe7125"
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
dependencies = [
"aes",
"byteorder",
+1 -2
View File
@@ -12,8 +12,7 @@ async fn main() {
let token = env::var("LIVEKIT_TOKEN").expect("LIVEKIT_TOKEN is not set");
let (room, mut rx) = Room::connect(&url, &token).await.unwrap();
let session = room.session();
log::info!("Connected to room: {} - {}", session.name(), session.sid());
log::info!("Connected to room: {} - {}", room.name(), room.sid());
while let Some(msg) = rx.recv().await {
log::info!("Event: {:?}", msg);
+1 -2
View File
@@ -90,8 +90,7 @@ async fn main() {
let token = env::var("LIVEKIT_TOKEN").expect("LIVEKIT_TOKEN is not set");
let (room, mut rx) = Room::connect(&url, &token).await.unwrap();
let session = room.session();
println!("Connected to room: {} - {}", session.name(), session.sid());
println!("Connected to room: {} - {}", room.name(), room.sid());
while let Some(msg) = rx.recv().await {
match msg {
+1 -3
View File
@@ -12,9 +12,7 @@ futures = "0.3"
wgpu = "0.16"
winit = "0.28"
parking_lot = "0.12.1"
image = "0.24"
egui = { git = "https://github.com/emilk/egui" }
egui-wgpu = { git = "https://github.com/emilk/egui", features = ["winit"] }
egui-winit = { git = "https://github.com/emilk/egui" }
image = "0.24"
+14 -16
View File
@@ -6,14 +6,8 @@ use crate::{events::AsyncCmd, video_grid::VideoGrid};
use egui::{Rounding, Stroke};
use egui_wgpu::WgpuConfiguration;
use futures::StreamExt;
use livekit::prelude::*;
use livekit::webrtc::audio_stream::native::NativeAudioStream;
use livekit::webrtc::video_frame::native::I420BufferExt;
use livekit::SimulateScenario;
use parking_lot::Mutex;
use std::collections::HashMap;
@@ -37,7 +31,7 @@ use winit::{
};
struct Session {
room: Room,
room: Arc<Room>,
logo_track: LogoTrack,
sine_track: SineTrack,
close_tx: oneshot::Sender<()>,
@@ -114,9 +108,10 @@ pub fn run(rt: tokio::runtime::Runtime) {
let res = Room::connect(&url, &token).await;
if let Ok((room, room_events)) = res {
let room = Arc::new(room);
let (close_tx, close_rx) = oneshot::channel();
let logo_track = LogoTrack::new(room.session());
let sine_track = SineTrack::new(room.session());
let logo_track = LogoTrack::new(room.clone());
let sine_track = SineTrack::new(room.clone());
let handle = tokio::spawn(room_task(
state.clone(),
room_events,
@@ -148,7 +143,7 @@ pub fn run(rt: tokio::runtime::Runtime) {
}
AsyncCmd::SimulateScenario { scenario } => {
if let Some(session) = state.session.lock().as_ref() {
let _ = session.room.session().simulate_scenario(scenario).await;
let _ = session.room.simulate_scenario(scenario).await;
}
}
AsyncCmd::ToggleLogo => {
@@ -164,7 +159,11 @@ pub fn run(rt: tokio::runtime::Runtime) {
AsyncCmd::ToggleSine => {
if let Some(session) = state.session.lock().as_mut() {
let sine_track = &mut session.sine_track;
sine_track.publish().await.unwrap();
if !sine_track.is_published() {
sine_track.publish().await.unwrap();
} else {
sine_track.unpublish().await.unwrap();
}
}
}
}
@@ -401,15 +400,15 @@ impl App {
{
// Room Info
if let Some(session) = self.state.session.lock().as_ref() {
ui.label(format!("Name: {}", session.room.session().name()));
ui.label(format!("SID: {}", session.room.session().sid()));
ui.label(format!("Name: {}", session.room.name()));
ui.label(format!("SID: {}", session.room.sid()));
ui.label(format!(
"ConnectionState: {:?}",
session.room.session().connection_state()
session.room.connection_state()
));
ui.label(format!(
"ParticipantCount: {:?}",
session.room.session().participants().len() + 1
session.room.participants().len() + 1
));
}
}
@@ -459,7 +458,6 @@ impl App {
self.state.session.lock().as_ref().and_then(|session| {
session
.room
.session()
.participants()
.get(participant_sid)
.map(|p| p.name())
+5 -5
View File
@@ -38,15 +38,15 @@ struct TrackHandle {
pub struct LogoTrack {
rtc_source: NativeVideoSource,
session: RoomSession,
room: Arc<Room>,
handle: Option<TrackHandle>,
}
impl LogoTrack {
pub fn new(session: RoomSession) -> Self {
pub fn new(room: Arc<Room>) -> Self {
Self {
rtc_source: NativeVideoSource::default(),
session,
room,
handle: None,
}
}
@@ -67,7 +67,7 @@ impl LogoTrack {
let task = tokio::spawn(Self::track_task(close_rx, self.rtc_source.clone()));
self.session
self.room
.local_participant()
.publish_track(
LocalTrack::Video(track.clone()),
@@ -93,7 +93,7 @@ impl LogoTrack {
let _ = handle.close_tx.send(());
let _ = handle.task.await;
self.session
self.room
.local_participant()
.unpublish_track(handle.track.sid(), true)
.await?;
+24 -19
View File
@@ -1,7 +1,6 @@
use livekit::options::{AudioCaptureOptions, TrackPublishOptions};
use livekit::webrtc::audio_frame::AudioFrame;
use livekit::{prelude::*, webrtc::audio_source::native::NativeAudioSource};
use parking_lot::Mutex;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::oneshot;
@@ -27,7 +26,6 @@ impl Default for FrameData {
}
struct TrackHandle {
frame_data: Arc<Mutex<FrameData>>,
close_tx: oneshot::Sender<()>,
track: LocalAudioTrack,
task: JoinHandle<()>,
@@ -35,19 +33,23 @@ struct TrackHandle {
pub struct SineTrack {
rtc_source: NativeAudioSource,
session: RoomSession,
room: Arc<Room>,
handle: Option<TrackHandle>,
}
impl SineTrack {
pub fn new(session: RoomSession) -> Self {
pub fn new(room: Arc<Room>) -> Self {
Self {
rtc_source: NativeAudioSource::default(),
session,
room,
handle: None,
}
}
pub fn is_published(&self) -> bool {
self.handle.is_some()
}
pub async fn publish(&mut self) -> Result<(), RoomError> {
let (close_tx, close_rx) = oneshot::channel();
let track = LocalAudioTrack::create_audio_track(
@@ -60,14 +62,9 @@ impl SineTrack {
self.rtc_source.clone(),
);
let data = Arc::new(Mutex::new(FrameData::default()));
let task = tokio::spawn(Self::track_task(
close_rx,
self.rtc_source.clone(),
data.clone(),
));
let task = tokio::spawn(Self::track_task(close_rx, self.rtc_source.clone()));
self.session
self.room
.local_participant()
.publish_track(
LocalTrack::Audio(track.clone()),
@@ -79,7 +76,6 @@ impl SineTrack {
.await?;
let handle = TrackHandle {
frame_data: data,
close_tx,
track,
task,
@@ -89,11 +85,21 @@ impl SineTrack {
Ok(())
}
async fn track_task(
_close_rx: oneshot::Receiver<()>,
rtc_source: NativeAudioSource,
frame_options: Arc<Mutex<FrameData>>,
) {
pub async fn unpublish(&mut self) -> Result<(), RoomError> {
if let Some(handle) = self.handle.take() {
handle.close_tx.send(()).ok();
handle.task.await.ok();
self.room
.local_participant()
.unpublish_track(handle.track.sid(), true)
.await?;
}
Ok(())
}
async fn track_task(_close_rx: oneshot::Receiver<()>, rtc_source: NativeAudioSource) {
let mut data = FrameData::default();
let mut interval = tokio::time::interval(Duration::from_millis(10));
let mut samples_10ms = Vec::<i16>::new();
@@ -102,7 +108,6 @@ impl SineTrack {
interval.tick().await;
let mut data = frame_options.lock();
let samples_count_10ms = (data.sample_rate / 100) as usize * NUM_CHANNELS;
if samples_10ms.capacity() != samples_count_10ms {
+1
View File
@@ -141,6 +141,7 @@ impl VideoGrid {
}
}
#[allow(dead_code)]
impl VideoGrid {
pub fn min_video_size(mut self, min_video_size: egui::Vec2) -> Self {
self.min_video_size = min_video_size;
+6 -7
View File
@@ -2,15 +2,14 @@ use futures::StreamExt;
use livekit::webrtc::native::yuv_helper;
use livekit::webrtc::prelude::*;
use livekit::webrtc::video_stream::native::NativeVideoStream;
use std::{
ops::DerefMut,
sync::{Arc, Mutex},
};
use parking_lot::Mutex;
use std::{ops::DerefMut, sync::Arc};
use tracing::debug_span;
pub struct VideoRenderer {
internal: Arc<Mutex<RendererInternal>>,
#[allow(dead_code)]
rtc_track: RtcVideoTrack,
}
@@ -109,7 +108,7 @@ impl VideoRenderer {
let span = debug_span!("texture_upload");
let _enter = span.enter();
let mut internal = internal.lock().unwrap();
let mut internal = internal.lock();
let buffer = frame.buffer.to_i420();
let width: u32 = buffer.width().try_into().unwrap();
@@ -174,6 +173,6 @@ impl VideoRenderer {
}
pub fn texture_id(&self) -> Option<egui::TextureId> {
self.internal.lock().unwrap().egui_texture.clone()
self.internal.lock().egui_texture.clone()
}
}
-3
View File
@@ -28,6 +28,3 @@ livekit-api = { path = "../livekit-api", version = "0.1.0" }
[lib]
crate-type = ["cdylib", "staticlib"]
[profile.release]
opt-level = "z"
+10 -10
View File
@@ -18,7 +18,7 @@ message AllocAudioBufferResponse { AudioFrameBufferInfo buffer = 1; }
// Create a new AudioStream
// AudioStream is used to receive audio frames from a track
message NewAudioStreamRequest {
FFIHandleId room_handle = 1;
FfiHandleId room_handle = 1;
string participant_sid = 2;
string track_sid = 3;
AudioStreamType type = 4;
@@ -31,21 +31,21 @@ message NewAudioSourceResponse { AudioSourceInfo source = 1; }
// Push a frame to an AudioSource
message CaptureAudioFrameRequest {
FFIHandleId source_handle = 1;
FFIHandleId buffer_handle = 2;
FfiHandleId source_handle = 1;
FfiHandleId buffer_handle = 2;
}
message CaptureAudioFrameResponse {}
// Create a new AudioResampler
message NewAudioResamplerRequest {}
message NewAudioResamplerResponse {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
}
// Remix and resample an audio frame
message RemixAndResampleRequest {
FFIHandleId resampler_handle = 1;
FFIHandleId buffer_handle = 2;
FfiHandleId resampler_handle = 1;
FfiHandleId buffer_handle = 2;
uint32 num_channels = 3;
uint32 sample_rate = 4;
}
@@ -59,7 +59,7 @@ message RemixAndResampleResponse {
///
message AudioFrameBufferInfo {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
uint64 data_ptr = 2; // *const i16
uint32 num_channels = 3;
uint32 sample_rate = 4;
@@ -76,13 +76,13 @@ enum AudioStreamType {
}
message AudioStreamInfo {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
AudioStreamType type = 2;
string track_sid = 3;
}
message AudioStreamEvent {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
oneof message { AudioFrameReceived frame_received = 2; }
}
@@ -99,6 +99,6 @@ enum AudioSourceType {
}
message AudioSourceInfo {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
AudioSourceType type = 2;
}
+7 -7
View File
@@ -12,7 +12,7 @@ import "audio_frame.proto";
/// This is the input of livekit_ffi_request function
/// We always expect a response (FFIResponse)
message FFIRequest {
message FfiRequest {
oneof message {
InitializeRequest initialize = 1;
DisposeRequest dispose = 2;
@@ -33,7 +33,7 @@ message FFIRequest {
NewVideoSourceRequest new_video_source = 11;
CaptureVideoFrameRequest capture_video_frame = 12;
ToI420Request to_i420 = 13;
ToARGBRequest to_argb = 14;
ToArgbRequest to_argb = 14;
// Audio
AllocAudioBufferRequest alloc_audio_buffer = 15;
@@ -46,7 +46,7 @@ message FFIRequest {
}
/// This is the output of livekit_ffi_request function.
message FFIResponse {
message FfiResponse {
oneof message {
InitializeResponse initialize = 1;
DisposeResponse dispose = 2;
@@ -67,7 +67,7 @@ message FFIResponse {
NewVideoSourceResponse new_video_source = 11;
CaptureVideoFrameResponse capture_video_frame = 12;
ToI420Response to_i420 = 13;
ToARGBResponse to_argb = 14;
ToArgbResponse to_argb = 14;
// Audio
AllocAudioBufferResponse alloc_audio_buffer = 15;
@@ -79,7 +79,7 @@ message FFIResponse {
}
}
message FFIEvent {
message FfiEvent {
oneof message {
RoomEvent room_event = 1;
TrackEvent track_event = 2;
@@ -104,11 +104,11 @@ message DisposeRequest {
}
message DisposeResponse {
optional FFIAsyncId async_id = 1; // None if sync
optional FfiAsyncId async_id = 1; // None if sync
}
message DisposeCallback {
FFIAsyncId async_id = 1;
FfiAsyncId async_id = 1;
}
// TODO(theomonnom): Debug messages (Print handles, forward logs).
+2 -2
View File
@@ -7,11 +7,11 @@ option csharp_namespace = "LiveKit.Proto";
/// The foreign language is responsable for disposing handles
/// Forgetting to dispose the handle may lead to memory leaks
/// Messages in this file can contain an FFIHandle
message FFIHandleId {
message FfiHandleId {
uint64 id = 1;
}
/// Link the request/response of an asynchronous call
message FFIAsyncId {
message FfiAsyncId {
uint64 id = 1;
}
+13 -13
View File
@@ -15,42 +15,42 @@ message ConnectRequest {
RoomOptions options = 3;
}
message ConnectResponse {
FFIAsyncId async_id = 1;
FfiAsyncId async_id = 1;
}
message ConnectCallback {
FFIAsyncId async_id = 1;
FfiAsyncId async_id = 1;
optional string error = 2;
RoomInfo room = 3;
}
// Disconnect from the a room
message DisconnectRequest { FFIHandleId room_handle = 1; }
message DisconnectResponse { FFIAsyncId async_id = 1; }
message DisconnectRequest { FfiHandleId room_handle = 1; }
message DisconnectResponse { FfiAsyncId async_id = 1; }
message DisconnectCallback { }
// Publish a track to the room
message PublishTrackRequest {
FFIHandleId room_handle = 1;
FFIHandleId track_handle = 2;
FfiHandleId room_handle = 1;
FfiHandleId track_handle = 2;
TrackPublishOptions options = 3;
}
message PublishTrackResponse {
FFIAsyncId async_id = 1;
FfiAsyncId async_id = 1;
}
message PublishTrackCallback {
FFIAsyncId async_id = 1;
FfiAsyncId async_id = 1;
optional string error = 2;
TrackPublicationInfo publication = 3;
}
// Unpublish a track from the room
message UnpublishTrackRequest {
FFIHandleId room_handle = 1;
FfiHandleId room_handle = 1;
string track_sid = 2;
bool stop_on_unpublish = 3;
}
message UnpublishTrackResponse {
FFIAsyncId async_id = 1;
FfiAsyncId async_id = 1;
}
message UnpublishTrackCallback {
optional string error = 1;
@@ -109,7 +109,7 @@ enum DataPacketKind {
}
message RoomEvent {
FFIHandleId room_handle = 1;
FfiHandleId room_handle = 1;
oneof message {
ParticipantConnected participant_connected = 2;
ParticipantDisconnected participant_disconnected = 3;
@@ -131,7 +131,7 @@ message RoomEvent {
}
message RoomInfo {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
string sid = 2;
string name = 3;
string metadata = 4;
@@ -140,7 +140,7 @@ message RoomInfo {
}
message DataReceived {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
optional string participant_sid = 2;
uint64 data_ptr = 3;
uint64 data_size = 4;
+3 -3
View File
@@ -21,7 +21,7 @@ message AudioCaptureOptions {
message CreateVideoTrackRequest {
string name = 1;
VideoCaptureOptions options = 2;
FFIHandleId source_handle = 3;
FfiHandleId source_handle = 3;
}
message CreateVideoTrackResponse {
TrackInfo track = 1;
@@ -31,7 +31,7 @@ message CreateVideoTrackResponse {
message CreateAudioTrackRequest {
string name = 1;
AudioCaptureOptions options = 2;
FFIHandleId source_handle = 3;
FfiHandleId source_handle = 3;
}
message CreateAudioTrackResponse {
TrackInfo track = 1;
@@ -80,7 +80,7 @@ message TrackPublicationInfo {
message TrackInfo {
// Tracks created/owned by the client will have a handle
FFIHandleId opt_handle = 1;
FfiHandleId opt_handle = 1;
string sid = 2;
string name = 3;
TrackKind kind = 4;
+11 -11
View File
@@ -16,7 +16,7 @@ message AllocVideoBufferResponse { VideoFrameBufferInfo buffer = 1; }
// Create a new VideoStream
// VideoStream is used to receive video frames from a track
message NewVideoStreamRequest {
FFIHandleId room_handle = 1;
FfiHandleId room_handle = 1;
string participant_sid = 2;
string track_sid = 3;
VideoStreamType type = 4;
@@ -30,9 +30,9 @@ message NewVideoSourceResponse { VideoSourceInfo source = 1; }
// Push a frame to a VideoSource
message CaptureVideoFrameRequest {
FFIHandleId source_handle = 1;
FfiHandleId source_handle = 1;
VideoFrameInfo frame = 2;
FFIHandleId buffer_handle = 3;
FfiHandleId buffer_handle = 3;
}
message CaptureVideoFrameResponse {}
@@ -42,15 +42,15 @@ message ToI420Request {
bool flip_y = 1;
oneof from {
ARGBBufferInfo argb = 2;
FFIHandleId buffer = 3;
FfiHandleId buffer = 3;
}
}
message ToI420Response { VideoFrameBufferInfo buffer = 1; }
// Convert a YUV frame to a RGBA frame
// Only I420 is supported atm
message ToARGBRequest {
FFIHandleId buffer = 1;
message ToArgbRequest {
FfiHandleId buffer = 1;
uint64 dst_ptr = 2;
VideoFormatType dst_format = 3;
uint32 dst_stride = 4;
@@ -58,7 +58,7 @@ message ToARGBRequest {
uint32 dst_height = 6;
bool flip_y = 7;
}
message ToARGBResponse {}
message ToArgbResponse {}
///
/// VideoFrame buffers ///
@@ -115,7 +115,7 @@ message VideoFrameInfo {
}
message VideoFrameBufferInfo {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
VideoFrameBufferType buffer_type = 2;
uint32 width = 3;
uint32 height = 4;
@@ -166,13 +166,13 @@ enum VideoStreamType {
}
message VideoStreamInfo {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
VideoStreamType type = 2;
string track_sid = 3;
}
message VideoStreamEvent {
FFIHandleId handle = 1;
FfiHandleId handle = 1;
oneof message { VideoFrameReceived frame_received = 2; }
}
@@ -192,7 +192,7 @@ enum VideoSourceType {
message VideoSourceInfo {
// # SAFETY
// This handle must not be dropped if a track is currently using it
FFIHandleId handle = 1;
FfiHandleId handle = 1;
VideoSourceType type = 2;
}
+1 -1
View File
@@ -66,7 +66,7 @@ impl proto::RoomEvent {
}
impl proto::RoomInfo {
pub fn from_session(handle_id: FfiHandleId, session: &RoomSession) -> Self {
pub fn from_room(handle_id: FfiHandleId, session: &Room) -> Self {
Self {
handle: Some(handle_id.into()),
sid: session.sid().into(),
+1
View File
@@ -60,6 +60,7 @@ impl_publication_into!(&TrackPublication);
macro_rules! impl_track_into {
($fnc:ident, $t:ty) => {
impl proto::TrackInfo {
#[allow(dead_code)]
pub fn $fnc(handle_id: FfiHandleId, track: $t) -> Self {
Self {
opt_handle: Some(handle_id.into()),
+1 -2
View File
@@ -157,8 +157,7 @@ impl FfiAudioSource {
proto::AudioSourceType::AudioSourceNative => {
let audio_source = NativeAudioSource::default();
Ok::<AudioSource, FfiError>(AudioSource::Native(audio_source))
}
_ => return Err(FfiError::InvalidRequest("unsupported audio source type")),
} //_ => return Err(FfiError::InvalidRequest("unsupported audio source type")),
}?;
let audio_source = Self {
+4 -4
View File
@@ -209,12 +209,12 @@ impl FfiServer {
.ok_or(FfiError::InvalidRequest("room_handle is empty"))?
.id as FfiHandleId;
let room = self
let ffi_room = self
.ffi_handles
.get(&room_handle)
.ok_or(FfiError::InvalidRequest("room not found"))?;
let room = room
let ffi_room = ffi_room
.downcast_ref::<room::FfiRoom>()
.ok_or(FfiError::InvalidRequest("room is not a FfiRoom"))?;
@@ -233,8 +233,8 @@ impl FfiServer {
.downcast_ref::<LocalTrack>()
.ok_or(FfiError::InvalidRequest("track is not a LocalTrack"))?;
let publication = room
.session()
let publication = ffi_room
.room()
.local_participant()
.publish_track(
track.clone(),
+16 -19
View File
@@ -1,12 +1,12 @@
use crate::server::FfiServer;
use crate::{proto, FfiHandleId, FfiResult};
use livekit::prelude::*;
use std::sync::Arc;
use tokio::sync::{mpsc, oneshot};
use tokio::task::JoinHandle;
pub struct FfiRoom {
room: Room,
handle_id: FfiHandleId,
room: Arc<Room>,
handle: JoinHandle<()>,
close_tx: oneshot::Sender<()>,
}
@@ -17,45 +17,42 @@ impl FfiRoom {
connect: proto::ConnectRequest,
) -> FfiResult<proto::RoomInfo> {
let (room, events) = Room::connect(&connect.url, &connect.token).await?;
let room = Arc::new(room);
let (close_tx, close_rx) = oneshot::channel();
let session = room.session();
let next_id = server.next_id() as FfiHandleId;
let handle = server.async_runtime.spawn(room_task(
server,
session.clone(),
next_id,
events,
close_rx,
));
let room_info = proto::RoomInfo::from_session(next_id, &session);
let handle =
server
.async_runtime
.spawn(room_task(server, room.clone(), next_id, events, close_rx));
let room_info = proto::RoomInfo::from_room(next_id, &room);
let ffi_room = Self {
handle_id: next_id,
room,
room: room.clone(),
handle,
close_tx,
};
server.ffi_handles().insert(next_id, Box::new(ffi_room));
server.rooms().lock().insert(session.sid(), next_id);
server.rooms().lock().insert(room.sid(), next_id);
Ok(room_info)
}
pub async fn close(self) {
self.room.close().await;
let _ = self.room.close().await;
let _ = self.close_tx.send(());
let _ = self.handle.await;
}
pub fn session(&self) -> RoomSession {
self.room.session()
pub fn room(&self) -> &Arc<Room> {
&self.room
}
}
async fn room_task(
server: &'static FfiServer,
session: RoomSession,
room: Arc<Room>,
room_handle: FfiHandleId,
mut events: mpsc::UnboundedReceiver<livekit::RoomEvent>,
mut close_rx: oneshot::Receiver<()>,
@@ -63,7 +60,7 @@ async fn room_task(
server
.async_runtime
.spawn(participant_task(Participant::Local(
session.local_participant(),
room.local_participant(),
)));
loop {
+5 -6
View File
@@ -12,8 +12,8 @@ mod client {
INVALID_HANDLE,
};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use prost::Message;
use std::sync::Mutex;
use tokio::sync::mpsc;
lazy_static! {
@@ -31,7 +31,7 @@ mod client {
impl Default for FfiClient {
fn default() -> Self {
let (event_tx, event_rx) = mpsc::unbounded_channel();
*EVENT_TX.lock().unwrap() = Some(event_tx);
*EVENT_TX.lock() = Some(event_tx);
Self { event_rx }
}
}
@@ -88,7 +88,6 @@ mod client {
let event = proto::FfiEvent::decode(data).unwrap();
EVENT_TX
.lock()
.unwrap()
.as_ref()
.unwrap()
.send(event.message.unwrap())
@@ -99,9 +98,9 @@ mod client {
struct TestScope {}
impl TestScope {
fn new() -> (Self, std::sync::MutexGuard<'static, client::FfiClient>) {
fn new() -> (Self, parking_lot::MutexGuard<'static, client::FfiClient>) {
// Run one test at a time
let client = client::FFI_CLIENT.lock().unwrap();
let client = client::FFI_CLIENT.lock();
(TestScope {}, client)
}
@@ -176,7 +175,7 @@ fn create_i420_buffer() {
#[test]
#[ignore] // Ignore for now ( need to setup GHA )
fn publish_video_track() {
let (test, mut client) = TestScope::new();
let (_test, mut client) = TestScope::new();
let (lk_url, lk_api_key, lk_api_secret) = test_env();
tokio::runtime::Builder::new_multi_thread()
+4 -4
View File
@@ -7,17 +7,17 @@ pub fn find_remote_track(
participant_sid: &ParticipantSid,
room_handle: FfiHandleId,
) -> FfiResult<RemoteTrack> {
let room = server
let ffi_room = server
.ffi_handles()
.get(&room_handle)
.ok_or(FfiError::InvalidRequest("room not found"))?;
let room = room
let ffi_room = ffi_room
.downcast_ref::<server::room::FfiRoom>()
.ok_or(FfiError::InvalidRequest("room is not ffi room"))?;
let session = room.session();
let participants = session.participants();
let room = ffi_room.room();
let participants = room.participants();
let participant = participants
.get(participant_sid)
.ok_or(FfiError::InvalidRequest("participant not found"))?;
+2 -3
View File
@@ -160,10 +160,9 @@ impl FfiVideoSource {
let source_inner = match source_type {
proto::VideoSourceType::VideoSourceNative => {
let video_source = NativeVideoSource::default();
Ok(VideoSource::Native(video_source))
VideoSource::Native(video_source)
}
_ => Err(FfiError::InvalidRequest("unsupported video source type")),
}?;
};
let video_source = Self {
handle_id: server.next_id(),
+3 -2
View File
@@ -1,6 +1,7 @@
use crate::audio_frame::AudioFrame;
use cxx::SharedPtr;
use std::sync::{Arc, Mutex};
use parking_lot::Mutex;
use std::sync::Arc;
use webrtc_sys::media_stream as sys_ms;
#[derive(Clone)]
@@ -32,7 +33,7 @@ impl NativeAudioSource {
}
pub fn capture_frame(&self, frame: &AudioFrame) {
let mut inner = self.inner.lock().unwrap();
let mut inner = self.inner.lock();
let samples_10ms = (frame.sample_rate / 100 * frame.num_channels) as usize;
if inner.sample_rate != frame.sample_rate || inner.num_channels != frame.num_channels {
inner.buf.resize(samples_10ms as usize, 0);
+8 -7
View File
@@ -3,8 +3,9 @@ use crate::data_channel::{
OnStateChange,
};
use cxx::SharedPtr;
use parking_lot::Mutex;
use std::str;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use webrtc_sys::data_channel as sys_dc;
impl From<sys_dc::ffi::DataState> for DataState {
@@ -94,15 +95,15 @@ impl DataChannel {
}
pub fn on_state_change(&self, handler: Option<OnStateChange>) {
*self.observer.state_change_handler.lock().unwrap() = handler;
*self.observer.state_change_handler.lock() = handler;
}
pub fn on_message(&self, handler: Option<OnMessage>) {
*self.observer.message_handler.lock().unwrap() = handler;
*self.observer.message_handler.lock() = handler;
}
pub fn on_buffered_amount_change(&self, handler: Option<OnBufferedAmountChange>) {
*self.observer.buffered_amount_change_handler.lock().unwrap() = handler;
*self.observer.buffered_amount_change_handler.lock() = handler;
}
}
@@ -115,21 +116,21 @@ struct DataChannelObserver {
impl sys_dc::DataChannelObserver for DataChannelObserver {
fn on_state_change(&self, state: sys_dc::ffi::DataState) {
let mut handler = self.state_change_handler.lock().unwrap();
let mut handler = self.state_change_handler.lock();
if let Some(f) = handler.as_mut() {
f(state.into());
}
}
fn on_message(&self, data: &[u8], binary: bool) {
let mut handler = self.message_handler.lock().unwrap();
let mut handler = self.message_handler.lock();
if let Some(f) = handler.as_mut() {
f(DataBuffer { data, binary });
}
}
fn on_buffered_amount_change(&self, sent_data_size: u64) {
let mut handler = self.buffered_amount_change_handler.lock().unwrap();
let mut handler = self.buffered_amount_change_handler.lock();
if let Some(f) = handler.as_mut() {
f(sent_data_size);
}
+20 -19
View File
@@ -23,8 +23,9 @@ use crate::MediaType;
use crate::{session_description::SessionDescription, RtcError};
use cxx::{SharedPtr, UniquePtr};
use futures::channel::oneshot;
use parking_lot::Mutex;
use std::mem::ManuallyDrop;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use webrtc_sys::data_channel as sys_dc;
use webrtc_sys::jsep as sys_jsep;
use webrtc_sys::peer_connection as sys_pc;
@@ -372,39 +373,39 @@ impl PeerConnection {
}
pub fn on_connection_state_change(&self, f: Option<OnConnectionChange>) {
*self.observer.connection_change_handler.lock().unwrap() = f;
*self.observer.connection_change_handler.lock() = f;
}
pub fn on_data_channel(&self, f: Option<OnDataChannel>) {
*self.observer.data_channel_handler.lock().unwrap() = f;
*self.observer.data_channel_handler.lock() = f;
}
pub fn on_ice_candidate(&self, f: Option<OnIceCandidate>) {
*self.observer.ice_candidate_handler.lock().unwrap() = f;
*self.observer.ice_candidate_handler.lock() = f;
}
pub fn on_ice_candidate_error(&self, f: Option<OnIceCandidateError>) {
*self.observer.ice_candidate_error_handler.lock().unwrap() = f;
*self.observer.ice_candidate_error_handler.lock() = f;
}
pub fn on_ice_connection_state_change(&self, f: Option<OnIceConnectionChange>) {
*self.observer.ice_connection_change_handler.lock().unwrap() = f;
*self.observer.ice_connection_change_handler.lock() = f;
}
pub fn on_ice_gathering_state_change(&self, f: Option<OnIceGatheringChange>) {
*self.observer.ice_gathering_change_handler.lock().unwrap() = f;
*self.observer.ice_gathering_change_handler.lock() = f;
}
pub fn on_negotiation_needed(&self, f: Option<OnNegotiationNeeded>) {
*self.observer.negotiation_needed_handler.lock().unwrap() = f;
*self.observer.negotiation_needed_handler.lock() = f;
}
pub fn on_signaling_state_change(&self, f: Option<OnSignalingChange>) {
*self.observer.signaling_change_handler.lock().unwrap() = f;
*self.observer.signaling_change_handler.lock() = f;
}
pub fn on_track(&self, f: Option<OnTrack>) {
*self.observer.track_handler.lock().unwrap() = f;
*self.observer.track_handler.lock() = f;
}
}
@@ -451,7 +452,7 @@ pub struct PeerObserver {
impl sys_pc::PeerConnectionObserver for PeerObserver {
fn on_signaling_change(&self, new_state: sys_pc::ffi::SignalingState) {
if let Some(f) = self.signaling_change_handler.lock().unwrap().as_mut() {
if let Some(f) = self.signaling_change_handler.lock().as_mut() {
f(new_state.into());
}
}
@@ -461,7 +462,7 @@ impl sys_pc::PeerConnectionObserver for PeerObserver {
fn on_remove_stream(&self, _stream: SharedPtr<webrtc_sys::media_stream::ffi::MediaStream>) {}
fn on_data_channel(&self, data_channel: SharedPtr<sys_dc::ffi::DataChannel>) {
if let Some(f) = self.data_channel_handler.lock().unwrap().as_mut() {
if let Some(f) = self.data_channel_handler.lock().as_mut() {
f(DataChannel {
handle: imp_dc::DataChannel::configure(data_channel),
});
@@ -471,7 +472,7 @@ impl sys_pc::PeerConnectionObserver for PeerObserver {
fn on_renegotiation_needed(&self) {}
fn on_negotiation_needed_event(&self, event: u32) {
if let Some(f) = self.negotiation_needed_handler.lock().unwrap().as_mut() {
if let Some(f) = self.negotiation_needed_handler.lock().as_mut() {
f(event);
}
}
@@ -479,25 +480,25 @@ impl sys_pc::PeerConnectionObserver for PeerObserver {
fn on_ice_connection_change(&self, _new_state: sys_pc::ffi::IceConnectionState) {}
fn on_standardized_ice_connection_change(&self, new_state: sys_pc::ffi::IceConnectionState) {
if let Some(f) = self.ice_connection_change_handler.lock().unwrap().as_mut() {
if let Some(f) = self.ice_connection_change_handler.lock().as_mut() {
f(new_state.into());
}
}
fn on_connection_change(&self, new_state: sys_pc::ffi::PeerConnectionState) {
if let Some(f) = self.connection_change_handler.lock().unwrap().as_mut() {
if let Some(f) = self.connection_change_handler.lock().as_mut() {
f(new_state.into());
}
}
fn on_ice_gathering_change(&self, new_state: sys_pc::ffi::IceGatheringState) {
if let Some(f) = self.ice_gathering_change_handler.lock().unwrap().as_mut() {
if let Some(f) = self.ice_gathering_change_handler.lock().as_mut() {
f(new_state.into());
}
}
fn on_ice_candidate(&self, candidate: SharedPtr<sys_jsep::ffi::IceCandidate>) {
if let Some(f) = self.ice_candidate_handler.lock().unwrap().as_mut() {
if let Some(f) = self.ice_candidate_handler.lock().as_mut() {
f(IceCandidate {
handle: imp_ic::IceCandidate {
sys_handle: candidate,
@@ -514,7 +515,7 @@ impl sys_pc::PeerConnectionObserver for PeerObserver {
error_code: i32,
error_text: String,
) {
if let Some(f) = self.ice_candidate_error_handler.lock().unwrap().as_mut() {
if let Some(f) = self.ice_candidate_error_handler.lock().as_mut() {
f(IceCandidateError {
address,
port,
@@ -547,7 +548,7 @@ impl sys_pc::PeerConnectionObserver for PeerObserver {
}
fn on_track(&self, transceiver: SharedPtr<webrtc_sys::rtp_transceiver::ffi::RtpTransceiver>) {
if let Some(f) = self.track_handler.lock().unwrap().as_mut() {
if let Some(f) = self.track_handler.lock().as_mut() {
let receiver = transceiver.receiver();
let streams = receiver.streams();
let track = receiver.track();
+1 -1
View File
@@ -1,6 +1,6 @@
pub use crate::participant::{LocalParticipant, Participant, ParticipantEvent, RemoteParticipant};
pub use crate::{ConnectionState, Room, RoomError, RoomEvent, RoomResult, RoomSession};
pub use crate::{ConnectionState, Room, RoomError, RoomEvent, RoomResult};
pub use crate::publication::{LocalTrackPublication, RemoteTrackPublication, TrackPublication};
+562 -15
View File
@@ -2,11 +2,19 @@ use self::track::RemoteTrack;
use crate::participant::ConnectionQuality;
use crate::prelude::*;
use crate::rtc_engine::EngineError;
use crate::rtc_engine::{EngineEvent, EngineEvents, EngineResult, RtcEngine};
use crate::signal_client::SignalOptions;
use livekit_protocol as proto;
use livekit_protocol::observer::Dispatcher;
use parking_lot::{Mutex, RwLock, RwLockReadGuard};
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
use thiserror::Error;
use tokio::sync::mpsc;
use tokio::sync::{mpsc, oneshot};
use tokio::task::JoinHandle;
use tracing::{error, info, instrument, trace, Level};
pub use crate::rtc_engine::SimulateScenario;
@@ -14,11 +22,8 @@ pub mod id;
pub mod options;
pub mod participant;
pub mod publication;
pub mod room_session;
pub mod track;
pub use room_session::*;
pub type RoomResult<T> = Result<T, RoomError>;
#[derive(Error, Debug)]
@@ -29,6 +34,8 @@ pub enum RoomError {
Internal(String),
#[error("this track or a track of the same source is already published")]
TrackAlreadyPublished,
#[error("already closed")]
AlreadyClosed,
}
#[derive(Clone, Debug)]
@@ -85,9 +92,32 @@ pub enum RoomEvent {
Reconnected,
}
#[derive(Debug)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ConnectionState {
Disconnected,
Connected,
Reconnecting,
Unknown,
}
struct RoomHandle {
session_task: JoinHandle<()>,
close_emitter: oneshot::Sender<()>,
}
pub struct Room {
handle: SessionHandle,
inner: Arc<SessionInner>,
handle: Mutex<Option<RoomHandle>>,
}
impl Debug for Room {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Room")
.field("sid", &self.sid())
.field("name", &self.name())
.field("connection_state", &self.connection_state())
.finish()
}
}
impl Room {
@@ -95,21 +125,538 @@ impl Room {
url: &str,
token: &str,
) -> RoomResult<(Self, mpsc::UnboundedReceiver<RoomEvent>)> {
let handle = SessionHandle::connect(url, token).await?;
let events = handle.subscribe();
Ok((Self { handle }, events))
let (rtc_engine, engine_events) = RtcEngine::new();
let rtc_engine = Arc::new(rtc_engine);
rtc_engine
.connect(url, token, SignalOptions::default())
.await?;
let join_response = rtc_engine.join_response().unwrap();
let pi = join_response.participant.unwrap().clone();
let local_participant = LocalParticipant::new(
rtc_engine.clone(),
pi.sid.into(),
pi.identity.into(),
pi.name,
pi.metadata,
);
let room_info = join_response.room.unwrap();
let inner = Arc::new(SessionInner {
state: AtomicU8::new(ConnectionState::Disconnected as u8),
sid: Mutex::new(room_info.sid.into()),
name: Mutex::new(room_info.name),
metadata: Mutex::new(room_info.metadata),
participants: Default::default(),
participants_tasks: Default::default(),
active_speakers: Default::default(),
rtc_engine,
local_participant,
dispatcher: Default::default(),
});
for pi in join_response.other_participants {
let participant = {
let pi = pi.clone();
inner.create_participant(pi.sid.into(), pi.identity.into(), pi.name, pi.metadata)
};
participant.update_info(pi.clone());
}
let (close_emitter, close_receiver) = oneshot::channel();
let session_task = tokio::spawn(inner.clone().room_task(engine_events, close_receiver));
inner.update_connection_state(ConnectionState::Connected);
let session = Self {
inner,
handle: Mutex::new(Some(RoomHandle {
session_task,
close_emitter,
})),
};
let events = session.subscribe();
Ok((session, events))
}
pub async fn close(self) {
self.handle.close().await;
pub async fn close(&self) -> RoomResult<()> {
if let Some(handle) = self.handle.lock().take() {
self.inner.close().await;
handle.close_emitter.send(()).ok();
handle.session_task.await.ok();
Ok(())
} else {
Err(RoomError::AlreadyClosed)
}
}
/// Allow multiple subscribers/observers to receive events
pub fn subscribe(&self) -> mpsc::UnboundedReceiver<RoomEvent> {
self.handle.subscribe()
self.inner.dispatcher.register()
}
pub fn session(&self) -> RoomSession {
self.handle.session()
pub fn sid(&self) -> RoomSid {
self.inner.sid.lock().clone()
}
pub fn name(&self) -> String {
self.inner.name.lock().clone()
}
pub fn metadata(&self) -> String {
self.inner.metadata.lock().clone()
}
pub fn local_participant(&self) -> LocalParticipant {
self.inner.local_participant.clone()
}
pub fn connection_state(&self) -> ConnectionState {
self.inner.state.load(Ordering::Acquire).try_into().unwrap()
}
pub fn participants(&self) -> RwLockReadGuard<HashMap<ParticipantSid, RemoteParticipant>> {
self.inner.participants.read()
}
pub async fn simulate_scenario(&self, scenario: SimulateScenario) -> EngineResult<()> {
self.inner.rtc_engine.simulate_scenario(scenario).await
}
}
struct SessionInner {
state: AtomicU8, // ConnectionState
sid: Mutex<RoomSid>,
name: Mutex<String>,
metadata: Mutex<String>,
participants: RwLock<HashMap<ParticipantSid, RemoteParticipant>>,
participants_tasks: RwLock<HashMap<ParticipantSid, (JoinHandle<()>, oneshot::Sender<()>)>>,
active_speakers: RwLock<Vec<Participant>>,
rtc_engine: Arc<RtcEngine>,
local_participant: LocalParticipant,
dispatcher: Dispatcher<RoomEvent>,
}
impl Debug for SessionInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SessionInner")
.field("sid", &self.sid)
.field("name", &self.name)
.field("rtc_engine", &self.rtc_engine)
.finish()
}
}
impl SessionInner {
#[instrument(level = Level::DEBUG)]
async fn room_task(
self: Arc<Self>,
mut engine_events: EngineEvents,
mut close_receiver: oneshot::Receiver<()>,
) {
loop {
tokio::select! {
res = engine_events.recv() => {
if let Some(event) = res {
if let Err(err) = self.on_engine_event(event).await {
error!("failed to handle engine event: {:?}", err);
}
}
},
_ = &mut close_receiver => {
trace!("closing room_task");
break;
}
}
}
}
/// Listen to the Participant events and forward them to the Room Dispatcher
#[instrument(level = Level::DEBUG)]
async fn participant_task(
self: Arc<Self>,
participant: Participant,
mut participant_events: mpsc::UnboundedReceiver<ParticipantEvent>,
mut close_rx: oneshot::Receiver<()>,
) {
loop {
tokio::select! {
res = participant_events.recv() => {
if let Some(event) = res {
if let Err(err) = self.on_participant_event(&participant, event).await {
error!("failed to handle participant event for {:?}: {:?}", participant.sid(), err);
}
}
},
_ = &mut close_rx => {
trace!("closing participant_task for {:?}", participant.sid());
break;
},
}
}
}
#[instrument(level = Level::DEBUG)]
async fn on_participant_event(
self: &Arc<Self>,
participant: &Participant,
event: ParticipantEvent,
) -> RoomResult<()> {
if let Participant::Remote(remote_participant) = participant {
match event {
ParticipantEvent::TrackPublished { publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackPublished {
participant: remote_participant.clone(),
publication,
});
}
ParticipantEvent::TrackUnpublished { publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackUnpublished {
participant: remote_participant.clone(),
publication,
});
}
ParticipantEvent::TrackSubscribed { track, publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackSubscribed {
participant: remote_participant.clone(),
track,
publication,
});
}
ParticipantEvent::TrackUnsubscribed { track, publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackUnsubscribed {
participant: remote_participant.clone(),
track,
publication,
});
}
_ => {}
};
}
Ok(())
}
#[instrument(level = Level::DEBUG)]
async fn on_engine_event(self: &Arc<Self>, event: EngineEvent) -> RoomResult<()> {
match event {
EngineEvent::ParticipantUpdate { updates } => self.handle_participant_update(updates),
EngineEvent::MediaTrack {
track,
stream,
receiver: _,
} => {
let stream_id = stream.id();
let lk_stream_id = unpack_stream_id(&stream_id);
if lk_stream_id.is_none() {
Err(RoomError::Internal(format!(
"MediaTrack event with invalid track_id: {:?}",
&stream_id
)))?;
}
let (participant_sid, track_sid) = lk_stream_id.unwrap();
let track_sid = track_sid.to_owned().into();
let remote_participant = self.get_participant(&participant_sid.to_string().into());
if let Some(remote_participant) = remote_participant {
tokio::spawn(async move {
remote_participant
.add_subscribed_media_track(track_sid, track)
.await;
});
} else {
// The server should send participant updates before sending a new offer
// So this should never happen.
Err(RoomError::Internal(format!(
"AddTrack event with invalid participant_sid: {:?}",
participant_sid
)))?;
}
}
EngineEvent::Resuming => {
if self.update_connection_state(ConnectionState::Reconnecting) {
self.dispatcher.dispatch(&RoomEvent::Reconnecting);
}
}
EngineEvent::Resumed => {
self.update_connection_state(ConnectionState::Connected);
self.dispatcher.dispatch(&RoomEvent::Reconnected);
// TODO(theomonnom): Update subscriptions settings
// TODO(theomonnom): Send sync state
}
EngineEvent::Restarting => self.handle_restarting(),
EngineEvent::Restarted => self.handle_restarted(),
EngineEvent::Disconnected => self.handle_disconnected(),
EngineEvent::Data {
payload,
kind,
participant_sid,
} => {
let payload = Arc::new(payload);
if let Some(participant) = self.get_participant(&participant_sid.into()) {
self.dispatcher.dispatch(&RoomEvent::DataReceived {
payload: payload.clone(),
kind,
participant: participant.clone(),
});
participant.on_data_received(payload, kind);
}
}
EngineEvent::SpeakersChanged { speakers } => self.handle_speakers_changed(speakers),
EngineEvent::ConnectionQuality { updates } => {
self.handle_connection_quality_update(updates)
}
}
Ok(())
}
#[instrument(level = Level::DEBUG)]
async fn close(&self) {
self.rtc_engine.close().await;
}
/// Change the connection state and emit an event
/// Does nothing if the state is already the same
#[instrument(level = Level::DEBUG)]
fn update_connection_state(&self, state: ConnectionState) -> bool {
let old_state = self.state.load(Ordering::Acquire);
if old_state == state as u8 {
return false;
}
self.state.store(state as u8, Ordering::Release);
self.dispatcher
.dispatch(&RoomEvent::ConnectionStateChanged(state));
return true;
}
/// Update the participants inside a Room.
/// It'll create, update or remove a participant
/// It also update the participant tracks.
#[instrument(level = Level::DEBUG)]
fn handle_participant_update(self: &Arc<Self>, updates: Vec<proto::ParticipantInfo>) {
for pi in updates {
if pi.sid == self.local_participant.sid()
|| pi.identity == self.local_participant.identity()
{
self.local_participant.clone().update_info(pi);
continue;
}
let remote_participant = self.get_participant(&pi.sid.clone().into());
if let Some(remote_participant) = remote_participant {
if pi.state == proto::participant_info::State::Disconnected as i32 {
// Participant disconnected
info!("Participant disconnected: {}", pi.sid);
self.clone()
.handle_participant_disconnect(remote_participant)
} else {
// Participant is already connected, update the it
remote_participant.update_info(pi.clone());
}
} else {
// Create a new participant
info!("Participant connected: {}", pi.sid);
let remote_participant = {
let pi = pi.clone();
self.create_participant(pi.sid.into(), pi.identity.into(), pi.name, pi.metadata)
};
let _ = self
.dispatcher
.dispatch(&RoomEvent::ParticipantConnected(remote_participant.clone()));
remote_participant.update_info(pi.clone());
}
}
}
/// Active speakers changed
/// Update the participants & sort the active_speakers by audio_level
#[instrument(level = Level::DEBUG)]
fn handle_speakers_changed(&self, speakers_info: Vec<proto::SpeakerInfo>) {
let mut speakers = Vec::new();
for speaker in speakers_info {
let participant = {
if speaker.sid == self.local_participant.sid() {
Participant::Local(self.local_participant.clone())
} else {
if let Some(participant) = self.get_participant(&speaker.sid.into()) {
Participant::Remote(participant)
} else {
continue;
}
}
};
participant.set_speaking(speaker.active);
participant.set_audio_level(speaker.level);
if speaker.active {
speakers.push(participant);
}
}
speakers.sort_by(|a, b| a.audio_level().partial_cmp(&b.audio_level()).unwrap());
*self.active_speakers.write() = speakers.clone();
let _ = self
.dispatcher
.dispatch(&RoomEvent::ActiveSpeakersChanged { speakers });
}
/// Handle a connection quality update
/// Emit ConnectionQualityChanged event for the concerned participants
#[instrument(level = Level::DEBUG)]
fn handle_connection_quality_update(&self, updates: Vec<proto::ConnectionQualityInfo>) {
for update in updates {
let participant = {
if update.participant_sid == self.local_participant.sid() {
Participant::Local(self.local_participant.clone())
} else {
if let Some(participant) = self.get_participant(&update.participant_sid.into())
{
Participant::Remote(participant)
} else {
continue;
}
}
};
let quality: ConnectionQuality = proto::ConnectionQuality::from_i32(update.quality)
.unwrap()
.into();
participant.set_connection_quality(quality);
self.dispatcher
.dispatch(&RoomEvent::ConnectionQualityChanged {
participant,
quality,
});
}
}
#[instrument(level = Level::DEBUG)]
fn handle_restarting(self: &Arc<Self>) {
// Remove existing participants/subscriptions on full reconnect
for (_, participant) in self.participants.read().iter() {
self.clone()
.handle_participant_disconnect(participant.clone());
}
if self.update_connection_state(ConnectionState::Reconnecting) {
self.dispatcher.dispatch(&RoomEvent::Reconnecting);
}
}
#[instrument(level = Level::DEBUG)]
fn handle_restarted(self: &Arc<Self>) {
// Full reconnect succeeded!
let join_response = self.rtc_engine.join_response().unwrap();
self.update_connection_state(ConnectionState::Connected);
self.dispatcher.dispatch(&RoomEvent::Reconnected);
if let Some(pi) = join_response.participant {
self.local_participant.update_info(pi); // The sid may have changed
}
self.handle_participant_update(join_response.other_participants);
// TODO(theomonnom): unpublish & republish tracks
}
#[instrument(level = Level::DEBUG)]
fn handle_disconnected(&self) {
if self.state.load(Ordering::Acquire) == ConnectionState::Disconnected as u8 {
return;
}
self.update_connection_state(ConnectionState::Disconnected);
self.dispatcher.dispatch(&RoomEvent::Disconnected);
}
/// Create a new participant
/// Also add it to the participants list
#[instrument(level = Level::DEBUG)]
fn create_participant(
self: &Arc<Self>,
sid: ParticipantSid,
identity: ParticipantIdentity,
name: String,
metadata: String,
) -> RemoteParticipant {
let participant = RemoteParticipant::new(sid.clone(), identity, name, metadata);
// Create the participant task
let (close_tx, close_rx) = oneshot::channel();
let participant_task = tokio::spawn(self.clone().participant_task(
Participant::Remote(participant.clone()),
participant.register_observer(),
close_rx,
));
self.participants_tasks
.write()
.insert(sid.clone(), (participant_task, close_tx));
self.participants.write().insert(sid, participant.clone());
participant
}
/// A participant has disconnected
/// Cleanup the participant and emit an event
#[instrument(level = Level::DEBUG)]
fn handle_participant_disconnect(self: Arc<Self>, remote_participant: RemoteParticipant) {
tokio::spawn(async move {
for (sid, _) in &*remote_participant.tracks() {
remote_participant.unpublish_track(&sid);
}
// Close the participant task
if let Some((task, close_tx)) = self
.participants_tasks
.write()
.remove(&remote_participant.sid())
{
let _ = close_tx.send(());
let _ = task.await;
}
self.participants.write().remove(&remote_participant.sid());
self.dispatcher
.dispatch(&RoomEvent::ParticipantDisconnected(remote_participant));
});
}
fn get_participant(&self, sid: &ParticipantSid) -> Option<RemoteParticipant> {
self.participants.read().get(sid).cloned()
}
}
fn unpack_stream_id(stream_id: &str) -> Option<(&str, &str)> {
let split: Vec<&str> = stream_id.split('|').collect();
if split.len() == 2 {
let participant_sid = split.get(0).unwrap();
let track_sid = split.get(1).unwrap();
Some((participant_sid, track_sid))
} else {
None
}
}
impl From<u8> for ConnectionState {
fn from(value: u8) -> Self {
match value {
0 => ConnectionState::Disconnected,
1 => ConnectionState::Connected,
2 => ConnectionState::Reconnecting,
_ => ConnectionState::Unknown,
}
}
}
-1
View File
@@ -1 +0,0 @@
@@ -9,16 +9,27 @@ use livekit_protocol as proto;
use livekit_webrtc::rtp_parameters::RtpEncodingParameters;
use parking_lot::RwLockReadGuard;
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::Arc;
use tokio::sync::mpsc;
use tracing::{debug, trace};
use tracing::debug;
#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct LocalParticipant {
inner: Arc<ParticipantInner>,
rtc_engine: Arc<RtcEngine>,
}
impl Debug for LocalParticipant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LocalParticipant")
.field("sid", &self.sid())
.field("identity", &self.identity())
.field("name", &self.name())
.finish()
}
}
impl LocalParticipant {
pub(crate) fn new(
rtc_engine: Arc<RtcEngine>,
@@ -110,7 +121,7 @@ impl LocalParticipant {
pub async fn unpublish_track(
&self,
track: TrackSid,
stop_on_unpublish: bool,
_stop_on_unpublish: bool,
) -> RoomResult<LocalTrackPublication> {
let mut tracks = self.inner.tracks.write();
if let Some(TrackPublication::Local(publication)) = tracks.remove(&track) {
+1
View File
@@ -5,6 +5,7 @@ use livekit_protocol::enum_dispatch;
use livekit_protocol::observer::Dispatcher;
use parking_lot::{Mutex, RwLock, RwLockReadGuard};
use std::collections::HashMap;
use std::fmt::Debug;
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering};
use std::sync::Arc;
use tokio::sync::mpsc;
@@ -6,6 +6,7 @@ use livekit_webrtc as rtc;
use parking_lot::RwLockReadGuard;
use rtc::prelude::MediaStreamTrack;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::mpsc;
@@ -14,11 +15,21 @@ use tracing::{debug, error, instrument, Level};
const ADD_TRACK_TIMEOUT: Duration = Duration::from_secs(5);
#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct RemoteParticipant {
inner: Arc<ParticipantInner>,
}
impl Debug for RemoteParticipant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RemoteParticipant")
.field("sid", &self.sid())
.field("identity", &self.identity())
.field("name", &self.name())
.finish()
}
}
impl RemoteParticipant {
pub(crate) fn new(
sid: ParticipantSid,
@@ -99,7 +110,6 @@ impl RemoteParticipant {
unreachable!()
}
}
_ => unreachable!(),
};
debug!("starting track: {:?}", sid);
+3
View File
@@ -9,6 +9,8 @@ use std::sync::Arc;
#[derive(Debug)]
struct LocalTrackPublicationInner {
publication_inner: TrackPublicationInner,
#[allow(unused)] // TODO(theomonnom)
options: Mutex<TrackPublishOptions>,
}
@@ -89,6 +91,7 @@ impl LocalTrackPublication {
self.inner.publication_inner.update_track(track);
}
#[allow(dead_code)]
#[inline]
pub(crate) fn update_info(&self, info: proto::TrackInfo) {
self.inner.publication_inner.update_info(info);
-563
View File
@@ -1,563 +0,0 @@
use crate::participant::ConnectionQuality;
use crate::prelude::*;
use crate::rtc_engine::{EngineEvent, EngineEvents, EngineResult, RtcEngine};
use crate::signal_client::SignalOptions;
use crate::{RoomError, RoomEvent, RoomResult, SimulateScenario};
use livekit_protocol as proto;
use livekit_protocol::observer::Dispatcher;
use parking_lot::{Mutex, RwLock, RwLockReadGuard};
use std::collections::HashMap;
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
use tokio::sync::{mpsc, oneshot};
use tokio::task::JoinHandle;
use tracing::{error, info, instrument, trace, Level};
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ConnectionState {
Disconnected,
Connected,
Reconnecting,
Unknown,
}
/// Internal representation of a RoomSession
#[derive(Debug)]
struct SessionInner {
state: AtomicU8, // ConnectionState
sid: Mutex<RoomSid>,
name: Mutex<String>,
metadata: Mutex<String>,
participants: RwLock<HashMap<ParticipantSid, RemoteParticipant>>,
participants_tasks: RwLock<HashMap<ParticipantSid, (JoinHandle<()>, oneshot::Sender<()>)>>,
active_speakers: RwLock<Vec<Participant>>,
rtc_engine: Arc<RtcEngine>,
local_participant: LocalParticipant,
dispatcher: Dispatcher<RoomEvent>,
}
#[derive(Debug)]
pub(crate) struct SessionHandle {
session: RoomSession,
session_task: JoinHandle<()>,
close_emitter: oneshot::Sender<()>,
}
/// RoomSession represents a connection to a room.
/// It can be cloned and shared across threads.
#[derive(Debug, Clone)]
pub struct RoomSession {
inner: Arc<SessionInner>,
}
impl SessionHandle {
pub async fn connect(url: &str, token: &str) -> RoomResult<Self> {
let (rtc_engine, engine_events) = RtcEngine::new();
let rtc_engine = Arc::new(rtc_engine);
rtc_engine
.connect(url, token, SignalOptions::default())
.await?;
let join_response = rtc_engine.join_response().unwrap();
let pi = join_response.participant.unwrap().clone();
let local_participant = LocalParticipant::new(
rtc_engine.clone(),
pi.sid.into(),
pi.identity.into(),
pi.name,
pi.metadata,
);
let room_info = join_response.room.unwrap();
let inner = Arc::new(SessionInner {
state: AtomicU8::new(ConnectionState::Disconnected as u8),
sid: Mutex::new(room_info.sid.into()),
name: Mutex::new(room_info.name),
metadata: Mutex::new(room_info.metadata),
participants: Default::default(),
participants_tasks: Default::default(),
active_speakers: Default::default(),
rtc_engine,
local_participant,
dispatcher: Default::default(),
});
for pi in join_response.other_participants {
let participant = {
let pi = pi.clone();
inner.create_participant(pi.sid.into(), pi.identity.into(), pi.name, pi.metadata)
};
participant.update_info(pi.clone());
}
let (close_emitter, close_receiver) = oneshot::channel();
let session_task = tokio::spawn(inner.clone().room_task(engine_events, close_receiver));
inner.update_connection_state(ConnectionState::Connected);
let session = Self {
session: RoomSession { inner },
session_task,
close_emitter,
};
Ok(session)
}
pub async fn close(self) {
self.session.inner.close().await;
let _ = self.close_emitter.send(());
let _ = self.session_task.await;
}
pub fn subscribe(&self) -> mpsc::UnboundedReceiver<RoomEvent> {
self.session.inner.dispatcher.register()
}
pub fn session(&self) -> RoomSession {
self.session.clone()
}
}
impl RoomSession {
pub fn sid(&self) -> RoomSid {
self.inner.sid.lock().clone()
}
pub fn name(&self) -> String {
self.inner.name.lock().clone()
}
pub fn metadata(&self) -> String {
self.inner.metadata.lock().clone()
}
pub fn local_participant(&self) -> LocalParticipant {
self.inner.local_participant.clone()
}
pub fn connection_state(&self) -> ConnectionState {
self.inner.state.load(Ordering::Acquire).try_into().unwrap()
}
pub fn participants(&self) -> RwLockReadGuard<HashMap<ParticipantSid, RemoteParticipant>> {
self.inner.participants.read()
}
pub async fn simulate_scenario(&self, scenario: SimulateScenario) -> EngineResult<()> {
self.inner.rtc_engine.simulate_scenario(scenario).await
}
}
impl SessionInner {
#[instrument(level = Level::DEBUG)]
async fn room_task(
self: Arc<Self>,
mut engine_events: EngineEvents,
mut close_receiver: oneshot::Receiver<()>,
) {
loop {
tokio::select! {
res = engine_events.recv() => {
if let Some(event) = res {
if let Err(err) = self.on_engine_event(event).await {
error!("failed to handle engine event: {:?}", err);
}
}
},
_ = &mut close_receiver => {
trace!("closing room_task");
break;
}
}
}
}
/// Listen to the Participant events and forward them to the Room Dispatcher
#[instrument(level = Level::DEBUG)]
async fn participant_task(
self: Arc<Self>,
participant: Participant,
mut participant_events: mpsc::UnboundedReceiver<ParticipantEvent>,
mut close_rx: oneshot::Receiver<()>,
) {
loop {
tokio::select! {
res = participant_events.recv() => {
if let Some(event) = res {
if let Err(err) = self.on_participant_event(&participant, event).await {
error!("failed to handle participant event for {:?}: {:?}", participant.sid(), err);
}
}
},
_ = &mut close_rx => {
trace!("closing participant_task for {:?}", participant.sid());
break;
},
}
}
}
#[instrument(level = Level::DEBUG)]
async fn on_participant_event(
self: &Arc<Self>,
participant: &Participant,
event: ParticipantEvent,
) -> RoomResult<()> {
if let Participant::Remote(remote_participant) = participant {
match event {
ParticipantEvent::TrackPublished { publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackPublished {
participant: remote_participant.clone(),
publication,
});
}
ParticipantEvent::TrackUnpublished { publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackUnpublished {
participant: remote_participant.clone(),
publication,
});
}
ParticipantEvent::TrackSubscribed { track, publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackSubscribed {
participant: remote_participant.clone(),
track,
publication,
});
}
ParticipantEvent::TrackUnsubscribed { track, publication } => {
self.dispatcher.dispatch(&RoomEvent::TrackUnsubscribed {
participant: remote_participant.clone(),
track,
publication,
});
}
_ => {}
};
}
Ok(())
}
#[instrument(level = Level::DEBUG)]
async fn on_engine_event(self: &Arc<Self>, event: EngineEvent) -> RoomResult<()> {
match event {
EngineEvent::ParticipantUpdate { updates } => self.handle_participant_update(updates),
EngineEvent::MediaTrack {
track,
stream,
receiver: _,
} => {
let stream_id = stream.id();
let lk_stream_id = unpack_stream_id(&stream_id);
if lk_stream_id.is_none() {
Err(RoomError::Internal(format!(
"MediaTrack event with invalid track_id: {:?}",
&stream_id
)))?;
}
let (participant_sid, track_sid) = lk_stream_id.unwrap();
let track_sid = track_sid.to_owned().into();
let remote_participant = self.get_participant(&participant_sid.to_string().into());
if let Some(remote_participant) = remote_participant {
tokio::spawn(async move {
remote_participant
.add_subscribed_media_track(track_sid, track)
.await;
});
} else {
// The server should send participant updates before sending a new offer
// So this should never happen.
Err(RoomError::Internal(format!(
"AddTrack event with invalid participant_sid: {:?}",
participant_sid
)))?;
}
}
EngineEvent::Resuming => {
if self.update_connection_state(ConnectionState::Reconnecting) {
self.dispatcher.dispatch(&RoomEvent::Reconnecting);
}
}
EngineEvent::Resumed => {
self.update_connection_state(ConnectionState::Connected);
self.dispatcher.dispatch(&RoomEvent::Reconnected);
// TODO(theomonnom): Update subscriptions settings
// TODO(theomonnom): Send sync state
}
EngineEvent::Restarting => self.handle_restarting(),
EngineEvent::Restarted => self.handle_restarted(),
EngineEvent::Disconnected => self.handle_disconnected(),
EngineEvent::Data {
payload,
kind,
participant_sid,
} => {
let payload = Arc::new(payload);
if let Some(participant) = self.get_participant(&participant_sid.into()) {
self.dispatcher.dispatch(&RoomEvent::DataReceived {
payload: payload.clone(),
kind,
participant: participant.clone(),
});
participant.on_data_received(payload, kind);
}
}
EngineEvent::SpeakersChanged { speakers } => self.handle_speakers_changed(speakers),
EngineEvent::ConnectionQuality { updates } => {
self.handle_connection_quality_update(updates)
}
}
Ok(())
}
#[instrument(level = Level::DEBUG)]
async fn close(&self) {
self.rtc_engine.close().await;
}
/// Change the connection state and emit an event
/// Does nothing if the state is already the same
#[instrument(level = Level::DEBUG)]
fn update_connection_state(&self, state: ConnectionState) -> bool {
let old_state = self.state.load(Ordering::Acquire);
if old_state == state as u8 {
return false;
}
self.state.store(state as u8, Ordering::Release);
self.dispatcher
.dispatch(&RoomEvent::ConnectionStateChanged(state));
return true;
}
/// Update the participants inside a Room.
/// It'll create, update or remove a participant
/// It also update the participant tracks.
#[instrument(level = Level::DEBUG)]
fn handle_participant_update(self: &Arc<Self>, updates: Vec<proto::ParticipantInfo>) {
for pi in updates {
if pi.sid == self.local_participant.sid()
|| pi.identity == self.local_participant.identity()
{
self.local_participant.clone().update_info(pi);
continue;
}
let remote_participant = self.get_participant(&pi.sid.clone().into());
if let Some(remote_participant) = remote_participant {
if pi.state == proto::participant_info::State::Disconnected as i32 {
// Participant disconnected
info!("Participant disconnected: {}", pi.sid);
self.clone()
.handle_participant_disconnect(remote_participant)
} else {
// Participant is already connected, update the it
remote_participant.update_info(pi.clone());
}
} else {
// Create a new participant
info!("Participant connected: {}", pi.sid);
let remote_participant = {
let pi = pi.clone();
self.create_participant(pi.sid.into(), pi.identity.into(), pi.name, pi.metadata)
};
let _ = self
.dispatcher
.dispatch(&RoomEvent::ParticipantConnected(remote_participant.clone()));
remote_participant.update_info(pi.clone());
}
}
}
/// Active speakers changed
/// Update the participants & sort the active_speakers by audio_level
#[instrument(level = Level::DEBUG)]
fn handle_speakers_changed(&self, speakers_info: Vec<proto::SpeakerInfo>) {
let mut speakers = Vec::new();
for speaker in speakers_info {
let participant = {
if speaker.sid == self.local_participant.sid() {
Participant::Local(self.local_participant.clone())
} else {
if let Some(participant) = self.get_participant(&speaker.sid.into()) {
Participant::Remote(participant)
} else {
continue;
}
}
};
participant.set_speaking(speaker.active);
participant.set_audio_level(speaker.level);
if speaker.active {
speakers.push(participant);
}
}
speakers.sort_by(|a, b| a.audio_level().partial_cmp(&b.audio_level()).unwrap());
*self.active_speakers.write() = speakers.clone();
let _ = self
.dispatcher
.dispatch(&RoomEvent::ActiveSpeakersChanged { speakers });
}
/// Handle a connection quality update
/// Emit ConnectionQualityChanged event for the concerned participants
#[instrument(level = Level::DEBUG)]
fn handle_connection_quality_update(&self, updates: Vec<proto::ConnectionQualityInfo>) {
for update in updates {
let participant = {
if update.participant_sid == self.local_participant.sid() {
Participant::Local(self.local_participant.clone())
} else {
if let Some(participant) = self.get_participant(&update.participant_sid.into())
{
Participant::Remote(participant)
} else {
continue;
}
}
};
let quality: ConnectionQuality = proto::ConnectionQuality::from_i32(update.quality)
.unwrap()
.into();
participant.set_connection_quality(quality);
self.dispatcher
.dispatch(&RoomEvent::ConnectionQualityChanged {
participant,
quality,
});
}
}
#[instrument(level = Level::DEBUG)]
fn handle_restarting(self: &Arc<Self>) {
// Remove existing participants/subscriptions on full reconnect
for (_, participant) in self.participants.read().iter() {
self.clone()
.handle_participant_disconnect(participant.clone());
}
if self.update_connection_state(ConnectionState::Reconnecting) {
self.dispatcher.dispatch(&RoomEvent::Reconnecting);
}
}
#[instrument(level = Level::DEBUG)]
fn handle_restarted(self: &Arc<Self>) {
// Full reconnect succeeded!
let join_response = self.rtc_engine.join_response().unwrap();
self.update_connection_state(ConnectionState::Connected);
self.dispatcher.dispatch(&RoomEvent::Reconnected);
if let Some(pi) = join_response.participant {
self.local_participant.update_info(pi); // The sid may have changed
}
self.handle_participant_update(join_response.other_participants);
// TODO(theomonnom): unpublish & republish tracks
}
#[instrument(level = Level::DEBUG)]
fn handle_disconnected(&self) {
if self.state.load(Ordering::Acquire) == ConnectionState::Disconnected as u8 {
return;
}
self.update_connection_state(ConnectionState::Disconnected);
self.dispatcher.dispatch(&RoomEvent::Disconnected);
}
/// Create a new participant
/// Also add it to the participants list
#[instrument(level = Level::DEBUG)]
fn create_participant(
self: &Arc<Self>,
sid: ParticipantSid,
identity: ParticipantIdentity,
name: String,
metadata: String,
) -> RemoteParticipant {
let participant = RemoteParticipant::new(sid.clone(), identity, name, metadata);
// Create the participant task
let (close_tx, close_rx) = oneshot::channel();
let participant_task = tokio::spawn(self.clone().participant_task(
Participant::Remote(participant.clone()),
participant.register_observer(),
close_rx,
));
self.participants_tasks
.write()
.insert(sid.clone(), (participant_task, close_tx));
self.participants.write().insert(sid, participant.clone());
participant
}
/// A participant has disconnected
/// Cleanup the participant and emit an event
#[instrument(level = Level::DEBUG)]
fn handle_participant_disconnect(self: Arc<Self>, remote_participant: RemoteParticipant) {
tokio::spawn(async move {
for (sid, _) in &*remote_participant.tracks() {
remote_participant.unpublish_track(&sid);
}
// Close the participant task
if let Some((task, close_tx)) = self
.participants_tasks
.write()
.remove(&remote_participant.sid())
{
let _ = close_tx.send(());
let _ = task.await;
}
self.participants.write().remove(&remote_participant.sid());
self.dispatcher
.dispatch(&RoomEvent::ParticipantDisconnected(remote_participant));
});
}
fn get_participant(&self, sid: &ParticipantSid) -> Option<RemoteParticipant> {
self.participants.read().get(sid).cloned()
}
}
fn unpack_stream_id(stream_id: &str) -> Option<(&str, &str)> {
let split: Vec<&str> = stream_id.split('|').collect();
if split.len() == 2 {
let participant_sid = split.get(0).unwrap();
let track_sid = split.get(1).unwrap();
Some((participant_sid, track_sid))
} else {
None
}
}
impl From<u8> for ConnectionState {
fn from(value: u8) -> Self {
match value {
0 => ConnectionState::Disconnected,
1 => ConnectionState::Connected,
2 => ConnectionState::Reconnecting,
_ => ConnectionState::Unknown,
}
}
}
+12 -1
View File
@@ -7,6 +7,7 @@ use livekit_protocol as proto;
use livekit_webrtc as rtc;
use parking_lot::Mutex;
use rtc::audio_source::native::NativeAudioSource;
use std::fmt::Debug;
use std::sync::Arc;
use tokio::sync::mpsc;
@@ -16,11 +17,21 @@ pub struct LocalAudioTrackInner {
capture_options: Mutex<AudioCaptureOptions>,
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct LocalAudioTrack {
inner: Arc<LocalAudioTrackInner>,
}
impl Debug for LocalAudioTrack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LocalAudioTrack")
.field("sid", &self.sid())
.field("name", &self.name())
.field("source", &self.source())
.finish()
}
}
impl LocalAudioTrack {
pub(crate) fn new(
name: String,
+12 -1
View File
@@ -6,6 +6,7 @@ use livekit_webrtc as rtc;
use livekit_webrtc::peer_connection_factory::native::PeerConnectionFactoryExt;
use parking_lot::Mutex;
use rtc::video_source::native::NativeVideoSource;
use std::fmt::Debug;
use std::sync::Arc;
use tokio::sync::mpsc;
@@ -15,11 +16,21 @@ struct LocalVideoTrackInner {
capture_options: Mutex<VideoCaptureOptions>,
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct LocalVideoTrack {
inner: Arc<LocalVideoTrackInner>,
}
impl Debug for LocalVideoTrack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LocalVideoTrack")
.field("sid", &self.sid())
.field("name", &self.name())
.field("source", &self.source())
.finish()
}
}
impl LocalVideoTrack {
pub fn new(
name: String,
+4 -4
View File
@@ -9,10 +9,10 @@ use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use thiserror::Error;
use tokio::sync::mpsc;
pub mod local_audio_track;
pub mod local_video_track;
pub mod remote_audio_track;
pub mod remote_video_track;
mod local_audio_track;
mod local_video_track;
mod remote_audio_track;
mod remote_video_track;
pub use local_audio_track::*;
pub use local_video_track::*;
+14 -1
View File
@@ -2,14 +2,25 @@ use super::TrackInner;
use crate::prelude::*;
use livekit_protocol as proto;
use livekit_webrtc as rtc;
use std::fmt::Debug;
use std::sync::Arc;
use tokio::sync::mpsc;
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct RemoteAudioTrack {
pub(crate) inner: Arc<TrackInner>,
}
impl Debug for RemoteAudioTrack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RemoteAudioTrack")
.field("sid", &self.sid())
.field("name", &self.name())
.field("source", &self.source())
.finish()
}
}
impl RemoteAudioTrack {
pub(crate) fn new(
sid: TrackSid,
@@ -90,12 +101,14 @@ impl RemoteAudioTrack {
true
}
#[allow(dead_code)]
#[inline]
pub(crate) fn transceiver(&self) -> Option<rtc::rtp_transceiver::RtpTransceiver> {
self.inner.transceiver()
}
#[inline]
#[allow(dead_code)]
pub(crate) fn update_transceiver(
&self,
transceiver: Option<rtc::rtp_transceiver::RtpTransceiver>,
+14 -1
View File
@@ -2,14 +2,25 @@ use super::TrackInner;
use crate::prelude::*;
use livekit_protocol as proto;
use livekit_webrtc as rtc;
use std::fmt::Debug;
use std::sync::Arc;
use tokio::sync::mpsc;
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct RemoteVideoTrack {
pub(crate) inner: Arc<TrackInner>,
}
impl Debug for RemoteVideoTrack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RemoteVideoTrack")
.field("sid", &self.sid())
.field("name", &self.name())
.field("source", &self.source())
.finish()
}
}
impl RemoteVideoTrack {
pub(crate) fn new(
sid: TrackSid,
@@ -90,11 +101,13 @@ impl RemoteVideoTrack {
true
}
#[allow(dead_code)]
#[inline]
pub(crate) fn transceiver(&self) -> Option<rtc::rtp_transceiver::RtpTransceiver> {
self.inner.transceiver()
}
#[allow(dead_code)]
#[inline]
pub(crate) fn update_transceiver(
&self,
+12 -1
View File
@@ -7,6 +7,7 @@ use livekit_protocol as proto;
use livekit_webrtc::prelude::*;
use livekit_webrtc::session_description::SdpParseError;
use parking_lot::Mutex;
use std::fmt::Debug;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
@@ -99,7 +100,6 @@ struct EngineHandle {
close_sender: oneshot::Sender<()>,
}
#[derive(Debug)]
struct EngineInner {
lk_runtime: Arc<LkRuntime>,
session_info: Mutex<Option<SessionInfo>>, // Last/Current Sessioninfo
@@ -113,6 +113,17 @@ struct EngineInner {
reconnect_interval: Mutex<Interval>,
}
impl Debug for EngineInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EngineInner")
.field("session_info", &self.session_info)
.field("opened", &self.opened)
.field("reconnecting", &self.reconnecting)
.field("full_reconnect", &self.full_reconnect)
.finish()
}
}
#[derive(Debug)]
pub struct RtcEngine {
inner: Arc<EngineInner>,
+1 -1
View File
@@ -4,7 +4,7 @@ use std::fmt::{Debug, Formatter};
use std::time::Duration;
use tracing::{event, Level};
const NEGOTIATION_FREQUENCY: Duration = Duration::from_millis(150);
const _NEGOTIATION_FREQUENCY: Duration = Duration::from_millis(150);
pub type OnOfferCreated = Box<dyn FnMut(SessionDescription) + Send + Sync>;
+1 -1
View File
@@ -3,7 +3,7 @@ use crate::rtc_engine::peer_transport::OnOfferCreated;
use livekit_protocol as proto;
use livekit_webrtc::{self as rtc, prelude::*};
use tokio::sync::mpsc;
use tracing::{debug, error};
use tracing::{error};
pub type RtcEmitter = mpsc::UnboundedSender<RtcEvent>;
pub type RtcEvents = mpsc::UnboundedReceiver<RtcEvent>;
+18 -1
View File
@@ -14,6 +14,7 @@ use prost::Message;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt::Debug;
use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::Arc;
use std::time::Duration;
@@ -104,7 +105,6 @@ pub struct SessionInfo {
}
/// Fields shared with rtc_task and signal_task
#[derive(Debug)]
struct SessionInner {
info: SessionInfo,
signal_client: Arc<SignalClient>,
@@ -128,6 +128,18 @@ struct SessionInner {
closed: AtomicBool,
emitter: SessionEmitter,
}
impl Debug for SessionInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SessionInner")
.field("info", &self.info)
.field("pc_state", &self.pc_state)
.field("has_published", &self.has_published)
.field("closed", &self.closed)
.finish()
}
}
/// This struct holds a WebRTC session
/// The session changes at every reconnection
///
@@ -317,6 +329,7 @@ impl RtcSession {
&self.inner.info
}
#[allow(dead_code)]
#[inline]
pub fn state(&self) -> PeerState {
self.inner
@@ -326,21 +339,25 @@ impl RtcSession {
.unwrap()
}
#[allow(dead_code)]
#[inline]
pub fn publisher(&self) -> &AsyncMutex<PeerTransport> {
&self.inner.publisher_pc
}
#[allow(dead_code)]
#[inline]
pub fn subscriber(&self) -> &AsyncMutex<PeerTransport> {
&self.inner.subscriber_pc
}
#[allow(dead_code)]
#[inline]
pub fn signal_client(&self) -> &Arc<SignalClient> {
&self.inner.signal_client
}
#[allow(dead_code)]
#[inline]
pub fn data_channel(&self, kind: proto::data_packet::Kind) -> &DataChannel {
&self.inner.data_channel(kind)
+3 -2
View File
@@ -1,6 +1,6 @@
use crate::signal_client::signal_stream::SignalStream;
use livekit_protocol as proto;
use livekit_webrtc::prelude::*;
use parking_lot::RwLock;
use std::fmt::Debug;
use std::time::Duration;
@@ -104,9 +104,10 @@ impl SignalClient {
// TODO(theomonnom): enqueue message
}
/*#[allow(dead_code)]
pub async fn clear_queue(&self) {
// TODO(theomonnom): impl
}
}*/
#[instrument(level = Level::DEBUG)]
pub async fn flush_queue(&self) {