Windows + Initial WebRTC sys & Safe WebRTC + Initial livekit-core
@@ -1,8 +1,3 @@
|
||||
target
|
||||
cmake-build-debug
|
||||
.idea/
|
||||
.cargo/
|
||||
test/
|
||||
libwebrtc/
|
||||
libwebrtc_android/
|
||||
CMakeLists.txt
|
||||
/target
|
||||
/.idea
|
||||
/libwebrtc
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "crates/livekit-core/protocol"]
|
||||
path = crates/livekit-core/protocol
|
||||
url = https://github.com/livekit/protocol
|
||||
@@ -1,20 +1,13 @@
|
||||
[package]
|
||||
name = "livekit-native"
|
||||
name = "livekit"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
homepage = "https://livekit.io"
|
||||
crate-type = ["lib"]
|
||||
repository = "https://github.com/livekit/client-sdk-native"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
cxx = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-build = "1.0"
|
||||
glob = "0.3.0"
|
||||
regex = "1.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib", "cdylib"]
|
||||
bench = false
|
||||
[workspace]
|
||||
exclude = ["libwebrtc"]
|
||||
members = [
|
||||
"crates/livekit-core",
|
||||
"crates/livekit-webrtc",
|
||||
"crates/livekit-webrtc/libwebrtc-sys"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,935 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
|
||||
[[package]]
|
||||
name = "livekit"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"futures-util",
|
||||
"log",
|
||||
"prost",
|
||||
"prost-build",
|
||||
"prost-types",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-build"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
"cmake",
|
||||
"heck",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"multimap",
|
||||
"petgraph",
|
||||
"prost",
|
||||
"prost-types",
|
||||
"regex",
|
||||
"tempfile",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-derive"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prost-types"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"tokio",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.17.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand",
|
||||
"sha-1",
|
||||
"thiserror",
|
||||
"url",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"matches",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
|
||||
dependencies = [
|
||||
"either",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "livekit-core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
crate-type = ["lib"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
tokio-tungstenite = "0.17.2"
|
||||
tokio = { version = "1.20.1", features = ["full"] }
|
||||
url = "2.2.2"
|
||||
futures-util = "0.3.23"
|
||||
thiserror = "1.0.32"
|
||||
prost = "0.10"
|
||||
prost-types = "0.10"
|
||||
anyhow = "1.0.63"
|
||||
|
||||
[build-dependencies]
|
||||
prost-build = { version = "0.10" }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.9"
|
||||
@@ -0,0 +1,12 @@
|
||||
use std::io::Result;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
prost_build::compile_protos(
|
||||
&[
|
||||
"protocol/livekit_rtc.proto",
|
||||
"protocol/livekit_models.proto",
|
||||
],
|
||||
&["protocol/"],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
pub mod proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/livekit.rs"));
|
||||
}
|
||||
|
||||
mod rtc_engine;
|
||||
mod signal_client;
|
||||
|
||||
pub mod room;
|
||||
@@ -0,0 +1 @@
|
||||
pub struct Room {}
|
||||
@@ -0,0 +1,60 @@
|
||||
use crate::proto::signal_response;
|
||||
use crate::signal_client::{SignalClient, SignalClientError};
|
||||
use log::error;
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
pub struct RTCEngine {
|
||||
signal_client: SignalClient,
|
||||
}
|
||||
|
||||
impl RTCEngine {
|
||||
pub fn new() -> RTCEngine {
|
||||
Self {
|
||||
signal_client: SignalClient::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn connect(&mut self, url: &str, token: &str) -> Result<(), SignalClientError> {
|
||||
self.signal_client.connect(url, token).await?;
|
||||
|
||||
tokio::spawn(Self::handle_rtc(
|
||||
self.signal_client.response_rx.resubscribe(),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn update(&self) {}
|
||||
|
||||
async fn handle_rtc(mut signal_receiver: broadcast::Receiver<signal_response::Message>) {
|
||||
loop {
|
||||
let msg = match signal_receiver.recv().await {
|
||||
Ok(msg) => msg,
|
||||
Err(error) => {
|
||||
error!("Failed to receive SignalResponse: {:?}", error);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
match msg {
|
||||
signal_response::Message::Join(join) => {}
|
||||
signal_response::Message::Trickle(trickle) => {}
|
||||
signal_response::Message::Answer(answer) => {}
|
||||
signal_response::Message::Offer(offer) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_test() {
|
||||
env_logger::init();
|
||||
|
||||
let mut engine = RTCEngine::new();
|
||||
engine.connect("ws://localhost:7880", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjQ1OTY4MDYsImlzcyI6IkFQSUNrSG04M01oZ2hQeCIsIm5hbWUiOiJ1c2VyMSIsIm5iZiI6MTY2MDk5NjgwNiwic3ViIjoidXNlcjEiLCJ2aWRlbyI6eyJyb29tIjoibXktZmlyc3Qtcm9vbSIsInJvb21Kb2luIjp0cnVlfX0.SWU_LETMK6ZmFOf38pYjVhpur0o7jJc6u61h8BH7g20").await.unwrap();
|
||||
|
||||
// Wait before exiting the program
|
||||
tokio::time::sleep(core::time::Duration::from_millis(1000 * 25)).await;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
use futures_util::SinkExt;
|
||||
use futures_util::StreamExt;
|
||||
use log::{error, info};
|
||||
use prost::Message as ProtoMessage;
|
||||
use std::borrow::Borrow;
|
||||
use thiserror::Error;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_tungstenite::tungstenite::Message;
|
||||
use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
|
||||
|
||||
use crate::{proto, proto::signal_response};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SignalClientError {
|
||||
#[error("websocket failure")]
|
||||
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
|
||||
#[error("failed to parse the url")]
|
||||
UrlParse(#[from] url::ParseError),
|
||||
#[error("failed to parse messages from server")]
|
||||
ProtoParse(#[from] prost::DecodeError),
|
||||
}
|
||||
|
||||
pub struct SignalClient {
|
||||
ws_handle: Option<JoinHandle<Result<(), SignalClientError>>>,
|
||||
response_tx: broadcast::Sender<signal_response::Message>,
|
||||
pub response_rx: broadcast::Receiver<signal_response::Message>,
|
||||
}
|
||||
|
||||
impl SignalClient {
|
||||
pub fn new() -> Self {
|
||||
let (tx, rx) = broadcast::channel(16);
|
||||
|
||||
Self {
|
||||
response_tx: tx,
|
||||
response_rx: rx,
|
||||
ws_handle: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn connect(&mut self, url: &str, token: &str) -> Result<(), SignalClientError> {
|
||||
let mut lk_url = url::Url::parse(url)?;
|
||||
lk_url.set_path("/rtc");
|
||||
lk_url
|
||||
.query_pairs_mut()
|
||||
.append_pair("access_token", token)
|
||||
.append_pair("protocol", "8");
|
||||
|
||||
info!("Connecting to {}", lk_url);
|
||||
let (ws, _) = connect_async(&lk_url).await?;
|
||||
|
||||
self.ws_handle = Some(tokio::spawn(Self::handle_ws(ws, self.response_tx.clone())));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn disconnect() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn handle_ws(
|
||||
mut ws: WebSocketStream<MaybeTlsStream<TcpStream>>,
|
||||
response_tx: broadcast::Sender<signal_response::Message>,
|
||||
) -> Result<(), SignalClientError> {
|
||||
loop {
|
||||
tokio::select! {
|
||||
next_msg = ws.next() => {
|
||||
let ws_msg = match next_msg {
|
||||
Some(msg) => msg?,
|
||||
None => break,
|
||||
};
|
||||
|
||||
let data = match ws_msg {
|
||||
Message::Binary(data) => data,
|
||||
Message::Ping(data) => {
|
||||
ws.send(Message::Pong(data)).await?;
|
||||
continue
|
||||
},
|
||||
Message::Close(_frame) => break,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let proto_msg = proto::SignalResponse::decode(data.borrow())?;
|
||||
let signal_response = proto_msg.message.unwrap();
|
||||
|
||||
match signal_response {
|
||||
signal_response::Message::Pong(ts) => {
|
||||
|
||||
},
|
||||
_ => {
|
||||
response_tx.send(signal_response).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "livekit-webrtc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
homepage = "https://livekit.io"
|
||||
|
||||
[dependencies]
|
||||
libwebrtc-sys = { path = "./libwebrtc-sys" }
|
||||
tokio = { version = "1.20.1", features = ["full"] }
|
||||
cxx = "1.0"
|
||||
log = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.9"
|
||||
@@ -0,0 +1,2 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-C", "target-feature=+crt-static"]
|
||||
@@ -0,0 +1,2 @@
|
||||
/libwebrtc
|
||||
/cmake-build-debug
|
||||
@@ -0,0 +1,23 @@
|
||||
# IMPORTANT NOTE
|
||||
# This file is just used because some IDEs need to understand how to do autocompletion.
|
||||
# This file is completely ignored by the library ( See build.rs for the build system )
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
project(livekit-webrtc)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_definitions(-DWEBRTC_WIN)
|
||||
|
||||
include_directories(libwebrtc/include)
|
||||
include_directories(libwebrtc/include/third_party/abseil-cpp/)
|
||||
include_directories(libwebrtc/include/third_party/libc++/)
|
||||
include_directories(include/)
|
||||
include_directories(../../../target/cxxbridge) # Can be different
|
||||
|
||||
file(GLOB_RECURSE SRC src/*.cpp)
|
||||
add_library(livekit-webrtc ${SRC})
|
||||
|
||||
#include_directories(/Users/theomonnom/Library/Android/sdk/ndk/25.0.8775105/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include)
|
||||
#find_library(ANDROID_LIB_ANDROID android)
|
||||
#target_link_libraries(client_sdk_native PRIVATE android)
|
||||
@@ -0,0 +1,213 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "873c2e83af70859af2aaecd1f5d862f3790b747b1f4f50fb45a931d000ac0422"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49edea7163bbc7a39e3d829b4b0b66a9d30486973152842b7413f2c7b5632bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46b787c15af80277db5c88c6ac6c502ae545e622f010e06f95e540d34931acf"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ba3f3a7efa46626878fb5d324fabca4d19d2956b6ae97ce43044ef4515f5abc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cae2cd7ba2f3f63938b9c724475dfb7b9861b545a90324476324ed21dbc8c8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "livekit-native"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
"glob",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "libwebrtc-sys"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
homepage = "https://livekit.io"
|
||||
|
||||
[dependencies]
|
||||
cxx = "1.0"
|
||||
log = "0.4"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-build = "1.0"
|
||||
glob = "0.3.0"
|
||||
regex = "1.0"
|
||||
cc = { version = "1.0", features = ["parallel"] }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.9"
|
||||
|
||||
#[lib]
|
||||
#crate-type = ["staticlib", "cdylib"]
|
||||
@@ -1,13 +1,58 @@
|
||||
use regex::Regex;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path;
|
||||
use std::process::Command;
|
||||
use regex::Regex;
|
||||
|
||||
const MAC_SDKS: &str =
|
||||
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs";
|
||||
|
||||
fn get_mac_sysroot() -> String {
|
||||
let mut sdks: Vec<String> = vec![];
|
||||
let files = fs::read_dir(MAC_SDKS).unwrap();
|
||||
for entry in files {
|
||||
let entry = entry.unwrap();
|
||||
let filename = entry.file_name().to_str().unwrap().to_owned();
|
||||
sdks.push(filename);
|
||||
}
|
||||
|
||||
sdks = sdks
|
||||
.iter()
|
||||
.filter(|value| value.contains("MacOSX1"))
|
||||
.map(|original| original.to_owned())
|
||||
.collect();
|
||||
|
||||
let last = sdks.last().unwrap();
|
||||
|
||||
format!("{}/{}", MAC_SDKS, &last)
|
||||
}
|
||||
|
||||
fn macos_link_search_path() -> Option<String> {
|
||||
let output = Command::new("clang")
|
||||
.arg("--print-search-dirs")
|
||||
.output()
|
||||
.ok()?;
|
||||
if !output.status.success() {
|
||||
// Failed to run 'clang --print-search-dirs'.
|
||||
return None;
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
for line in stdout.lines() {
|
||||
if line.contains("libraries: =") {
|
||||
let path = line.split('=').nth(1)?;
|
||||
return Some(format!("{}/lib/darwin", path));
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to determine link search path.
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// TODO Download precompiled binaries of WebRTC for the target_os
|
||||
|
||||
let target_os = "ios";
|
||||
let target_os = "windows";
|
||||
//let target_arch = "arm64";
|
||||
|
||||
let libwebrtc_dir = path::PathBuf::from("libwebrtc");
|
||||
@@ -18,15 +63,32 @@ fn main() {
|
||||
libwebrtc_dir.join("include/"),
|
||||
libwebrtc_dir.join("include/third_party/abseil-cpp/"),
|
||||
libwebrtc_dir.join("include/third_party/libc++/"),
|
||||
|
||||
// For mac & ios
|
||||
libwebrtc_dir.join("include/sdk/objc"),
|
||||
libwebrtc_dir.join("include/sdk/objc/base"),
|
||||
];
|
||||
|
||||
let mut builder = cxx_build::bridges(&["src/lib.rs"]);
|
||||
builder.flag("-std=c++17");
|
||||
let mut builder = cxx_build::bridges(&[
|
||||
"src/peer_connection.rs",
|
||||
"src/peer_connection_factory.rs",
|
||||
"src/media_stream_interface.rs",
|
||||
"src/data_channel.rs",
|
||||
"src/jsep.rs",
|
||||
"src/candidate.rs",
|
||||
"src/rtp_receiver.rs",
|
||||
"src/rtp_transceiver.rs",
|
||||
"src/rtc_error.rs",
|
||||
]);
|
||||
|
||||
builder.file("src/peer_connection.cpp");
|
||||
builder.file("src/peer_connection_factory.cpp");
|
||||
builder.file("src/media_stream_interface.cpp");
|
||||
builder.file("src/data_channel.cpp");
|
||||
builder.file("src/jsep.cpp");
|
||||
builder.file("src/candidate.cpp");
|
||||
builder.file("src/rtp_receiver.cpp");
|
||||
builder.file("src/rtp_transceiver.cpp");
|
||||
builder.file("src/rtc_error.cpp");
|
||||
|
||||
for include in includes {
|
||||
builder.include(include);
|
||||
@@ -38,6 +100,28 @@ fn main() {
|
||||
);
|
||||
|
||||
match target_os {
|
||||
"windows" => {
|
||||
println!("cargo:rustc-link-lib=dylib=msdmo");
|
||||
println!("cargo:rustc-link-lib=dylib=wmcodecdspuuid");
|
||||
println!("cargo:rustc-link-lib=dylib=dmoguids");
|
||||
println!("cargo:rustc-link-lib=dylib=crypt32");
|
||||
println!("cargo:rustc-link-lib=dylib=iphlpapi");
|
||||
println!("cargo:rustc-link-lib=dylib=ole32");
|
||||
println!("cargo:rustc-link-lib=dylib=secur32");
|
||||
println!("cargo:rustc-link-lib=dylib=winmm");
|
||||
println!("cargo:rustc-link-lib=dylib=ws2_32");
|
||||
println!("cargo:rustc-link-lib=dylib=strmiids");
|
||||
println!("cargo:rustc-link-lib=dylib=d3d11");
|
||||
println!("cargo:rustc-link-lib=dylib=dxgi");
|
||||
println!("cargo:rustc-link-lib=dylib=dwmapi");
|
||||
println!("cargo:rustc-link-lib=dylib=webrtc");
|
||||
|
||||
builder
|
||||
.flag("/std:c++17")
|
||||
.flag("/EHsc")
|
||||
.define("WEBRTC_WIN", None)
|
||||
.define("NOMINMAX", None);
|
||||
}
|
||||
"macos" => {
|
||||
println!("cargo:rustc-link-lib=dylib=c++");
|
||||
println!("cargo:rustc-link-lib=framework=Foundation");
|
||||
@@ -47,16 +131,31 @@ fn main() {
|
||||
println!("cargo:rustc-link-lib=framework=Appkit");
|
||||
println!("cargo:rustc-link-lib=framework=CoreMedia");
|
||||
println!("cargo:rustc-link-lib=framework=CoreGraphics");
|
||||
println!("cargo:rustc-link-lib=framework=VideoToolbox");
|
||||
println!("cargo:rustc-link-lib=framework=CoreVideo");
|
||||
println!("cargo:rustc-link-lib=framework=OpenGL");
|
||||
println!("cargo:rustc-link-lib=framework=Metal");
|
||||
println!("cargo:rustc-link-lib=framework=QuartzCore");
|
||||
println!("cargo:rustc-link-lib=framework=IOKit");
|
||||
println!("cargo:rustc-link-lib=framework=IOSurface");
|
||||
println!("cargo:rustc-link-lib=static=webrtc");
|
||||
|
||||
builder
|
||||
.flag("-stdlib=libc++")
|
||||
.flag("-std=c++17")
|
||||
.flag(format!("-isysroot{}", get_mac_sysroot()).as_str())
|
||||
.define("WEBRTC_ENABLE_OBJC_SYMBOL_EXPORT", None)
|
||||
.define("WEBRTC_POSIX", None)
|
||||
.define("WEBRTC_MAC", None);
|
||||
|
||||
if let Some(path) = macos_link_search_path() {
|
||||
println!("cargo:rustc-link-lib=clang_rt.osx");
|
||||
println!("cargo:rustc-link-search={}", path);
|
||||
}
|
||||
}
|
||||
"ios" => {
|
||||
|
||||
builder
|
||||
.flag("-std=c++17")
|
||||
.file("src/objc_test.mm")
|
||||
.define("WEBRTC_ENABLE_OBJC_SYMBOL_EXPORT", None)
|
||||
.define("WEBRTC_MAC", None)
|
||||
@@ -84,10 +183,7 @@ fn main() {
|
||||
// libgcc ( redirects to libunwind )
|
||||
println!(
|
||||
"cargo:rustc-link-search={}",
|
||||
toolchain
|
||||
.join("lib")
|
||||
.to_str()
|
||||
.unwrap()
|
||||
toolchain.join("lib").to_str().unwrap()
|
||||
);
|
||||
|
||||
// Needed when loading the library in the JVM ( System.loadLibrary )
|
||||
@@ -129,12 +225,13 @@ fn main() {
|
||||
);
|
||||
|
||||
builder
|
||||
.flag("-std=c++17")
|
||||
.define("WEBRTC_LINUX", None)
|
||||
.define("WEBRTC_POSIX", None)
|
||||
.define("WEBRTC_ANDROID", None);
|
||||
}
|
||||
_ => {
|
||||
panic!("Unsupported platform, {}", target_os);
|
||||
panic!("Unsupported target, {}", target_os);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_CANDIDATE_H
|
||||
#define CLIENT_SDK_NATIVE_CANDIDATE_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/candidate.h"
|
||||
|
||||
// cricket::Candidate
|
||||
namespace livekit {
|
||||
|
||||
class Candidate {
|
||||
public:
|
||||
explicit Candidate(const cricket::Candidate &candidate);
|
||||
|
||||
private:
|
||||
cricket::Candidate candidate_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<Candidate> _unique_candidate(){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_CANDIDATE_H
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_DATA_CHANNEL_H
|
||||
#define CLIENT_SDK_NATIVE_DATA_CHANNEL_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/data_channel_interface.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
class DataChannel {
|
||||
public:
|
||||
explicit DataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel);
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<DataChannel> _unique_data_channel(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_DATA_CHANNEL_H
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_JSEP_H
|
||||
#define CLIENT_SDK_NATIVE_JSEP_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/jsep.h"
|
||||
#include "rust/cxx.h"
|
||||
#include "rust_types.h"
|
||||
#include "api/ref_counted_base.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
class IceCandidate {
|
||||
public:
|
||||
explicit IceCandidate(std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate);
|
||||
|
||||
private:
|
||||
std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<IceCandidate> _unique_ice_candidate(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
|
||||
class SessionDescription {
|
||||
public:
|
||||
explicit SessionDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> session_description);
|
||||
|
||||
std::unique_ptr<SessionDescription> clone() const;
|
||||
std::unique_ptr<webrtc::SessionDescriptionInterface> release();
|
||||
|
||||
private:
|
||||
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<SessionDescription> _unique_session_description(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
|
||||
// SetCreateSdpObserver
|
||||
|
||||
class NativeCreateSdpObserver : public webrtc::CreateSessionDescriptionObserver {
|
||||
public:
|
||||
explicit NativeCreateSdpObserver(rust::Box<CreateSdpObserverWrapper> observer);
|
||||
|
||||
void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
|
||||
void OnFailure(webrtc::RTCError error) override;
|
||||
private:
|
||||
rust::Box<CreateSdpObserverWrapper> observer_;
|
||||
};
|
||||
|
||||
struct NativeCreateSdpObserverHandle {
|
||||
rtc::scoped_refptr<NativeCreateSdpObserver> observer;
|
||||
};
|
||||
|
||||
std::unique_ptr<NativeCreateSdpObserverHandle> create_native_create_sdp_observer(rust::Box<CreateSdpObserverWrapper> observer);
|
||||
|
||||
// SetLocalSdpObserver
|
||||
|
||||
class NativeSetLocalSdpObserver : public webrtc::SetLocalDescriptionObserverInterface{
|
||||
public:
|
||||
explicit NativeSetLocalSdpObserver(rust::Box<SetLocalSdpObserverWrapper> observer);
|
||||
|
||||
void OnSetLocalDescriptionComplete(webrtc::RTCError error) override;
|
||||
private:
|
||||
rust::Box<SetLocalSdpObserverWrapper> observer_;
|
||||
};
|
||||
|
||||
struct NativeSetLocalSdpObserverHandle {
|
||||
rtc::scoped_refptr<NativeSetLocalSdpObserver> observer;
|
||||
};
|
||||
|
||||
std::unique_ptr<NativeSetLocalSdpObserverHandle> create_native_set_local_sdp_observer(rust::Box<SetLocalSdpObserverWrapper> observer);
|
||||
|
||||
// SetRemoteSdpObserver
|
||||
|
||||
class NativeSetRemoteSdpObserver : public webrtc::SetRemoteDescriptionObserverInterface{
|
||||
public:
|
||||
explicit NativeSetRemoteSdpObserver(rust::Box<SetRemoteSdpObserverWrapper> observer);
|
||||
|
||||
void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override;
|
||||
private:
|
||||
rust::Box<SetRemoteSdpObserverWrapper> observer_;
|
||||
};
|
||||
|
||||
struct NativeSetRemoteSdpObserverHandle {
|
||||
rtc::scoped_refptr<NativeSetRemoteSdpObserver> observer;
|
||||
};
|
||||
|
||||
std::unique_ptr<NativeSetRemoteSdpObserverHandle> create_native_set_remote_sdp_observer(rust::Box<SetRemoteSdpObserverWrapper> observer);
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_JSEP_H
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Théo Monnom on 31/08/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_MEDIA_STREAM_INTERFACE_H
|
||||
#define CLIENT_SDK_NATIVE_MEDIA_STREAM_INTERFACE_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/media_stream_interface.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
class MediaStreamInterface {
|
||||
public:
|
||||
explicit MediaStreamInterface(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream);
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<webrtc::MediaStreamInterface> media_stream_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<MediaStreamInterface> _unique_media_stream(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_MEDIA_STREAM_INTERFACE_H
|
||||
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// Created by Théo Monnom on 30/08/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_PEER_CONNECTION_H
|
||||
#define CLIENT_SDK_NATIVE_PEER_CONNECTION_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "rust/cxx.h"
|
||||
#include "data_channel.h"
|
||||
#include "jsep.h"
|
||||
#include "rust_types.h"
|
||||
|
||||
namespace livekit {
|
||||
class NativePeerConnectionObserver;
|
||||
|
||||
class PeerConnection {
|
||||
public:
|
||||
explicit PeerConnection(rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection, std::unique_ptr<NativePeerConnectionObserver> observer);
|
||||
|
||||
void close();
|
||||
void create_offer(std::unique_ptr<NativeCreateSdpObserverHandle> observer, RTCOfferAnswerOptions options);
|
||||
void create_answer(std::unique_ptr<NativeCreateSdpObserverHandle> observer, RTCOfferAnswerOptions options);
|
||||
void set_local_description(std::unique_ptr<SessionDescription> desc, std::unique_ptr<NativeSetLocalSdpObserverHandle> observer);
|
||||
void set_remote_description(std::unique_ptr<SessionDescription> desc, std::unique_ptr<NativeSetRemoteSdpObserverHandle> observer);
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
|
||||
std::unique_ptr<NativePeerConnectionObserver> observer_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<PeerConnection> _unique_peer_connection() {
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
|
||||
class NativePeerConnectionObserver : public webrtc::PeerConnectionObserver {
|
||||
public:
|
||||
explicit NativePeerConnectionObserver(rust::Box<PeerConnectionObserverWrapper> observer);
|
||||
|
||||
~NativePeerConnectionObserver() override = default;
|
||||
|
||||
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override;
|
||||
void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
||||
void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) override;
|
||||
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override;
|
||||
void OnRenegotiationNeeded() override;
|
||||
void OnNegotiationNeededEvent(uint32_t event_id) override;
|
||||
void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override;
|
||||
void OnStandardizedIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override;
|
||||
void OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) override;
|
||||
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override;
|
||||
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override;
|
||||
void OnIceCandidateError(const std::string &address, int port, const std::string &url, int error_code, const std::string &error_text) override;
|
||||
void OnIceCandidatesRemoved(const std::vector<cricket::Candidate> &candidates) override;
|
||||
void OnIceConnectionReceivingChange(bool receiving) override;
|
||||
void OnIceSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent &event) override;
|
||||
void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) override;
|
||||
void OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) override;
|
||||
void OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) override;
|
||||
void OnInterestingUsage(int usage_pattern) override;
|
||||
|
||||
private:
|
||||
rust::Box<PeerConnectionObserverWrapper> observer_;
|
||||
};
|
||||
|
||||
std::unique_ptr<NativePeerConnectionObserver> create_native_peer_connection_observer(rust::Box<PeerConnectionObserverWrapper> observer);
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_PEER_CONNECTION_H
|
||||
|
||||
@@ -7,24 +7,29 @@
|
||||
#define PEER_CONNECTION_FACTORY_H
|
||||
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "peer_connection.h"
|
||||
#include "rust_types.h"
|
||||
|
||||
namespace lk {
|
||||
namespace livekit {
|
||||
using NativeRTCConfiguration = webrtc::PeerConnectionInterface::RTCConfiguration;
|
||||
|
||||
class PeerConnectionFactory {
|
||||
public:
|
||||
PeerConnectionFactory();
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
|
||||
std::unique_ptr<PeerConnection> create_peer_connection(std::unique_ptr<NativeRTCConfiguration> config, std::unique_ptr<NativePeerConnectionObserver> observer) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<rtc::Thread> network_thread_;
|
||||
std::unique_ptr<rtc::Thread> worker_thread_;
|
||||
std::unique_ptr<rtc::Thread> signaling_thread_;
|
||||
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_factory_;
|
||||
};
|
||||
|
||||
std::unique_ptr<PeerConnectionFactory> CreatePeerConnectionFactory();
|
||||
|
||||
}
|
||||
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory();
|
||||
std::unique_ptr<NativeRTCConfiguration> create_rtc_configuration(RTCConfiguration conf);
|
||||
} // livekit
|
||||
|
||||
|
||||
#endif //PEER_CONNECTION_FACTORY_H
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by theom on 04/09/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_RTC_ERROR_H
|
||||
#define CLIENT_SDK_NATIVE_RTC_ERROR_H
|
||||
|
||||
#include "api/rtc_error.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
class RTCError {
|
||||
public:
|
||||
explicit RTCError(webrtc::RTCError error);
|
||||
|
||||
private:
|
||||
webrtc::RTCError rtc_error_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<RTCError> _unique_rtc_error(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_RTC_ERROR_H
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_RTP_RECEIVER_H
|
||||
#define CLIENT_SDK_NATIVE_RTP_RECEIVER_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/rtp_receiver_interface.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
class RtpReceiver {
|
||||
public:
|
||||
explicit RtpReceiver(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver);
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<RtpReceiver> _unique_rtp_receiver(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_RTP_RECEIVER_H
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by Théo Monnom on 02/09/2022.
|
||||
//
|
||||
|
||||
#ifndef CLIENT_SDK_NATIVE_RTP_TRANSCEIVER_H
|
||||
#define CLIENT_SDK_NATIVE_RTP_TRANSCEIVER_H
|
||||
|
||||
#include <memory>
|
||||
#include "api/rtp_transceiver_interface.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
class RtpTransceiver {
|
||||
public:
|
||||
explicit RtpTransceiver(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver);
|
||||
|
||||
private:
|
||||
rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver_;
|
||||
};
|
||||
|
||||
static std::unique_ptr<RtpTransceiver> _unique_rtp_transceiver(){
|
||||
return nullptr; // Ignore
|
||||
}
|
||||
} // livekit
|
||||
|
||||
#endif //CLIENT_SDK_NATIVE_RTP_TRANSCEIVER_H
|
||||
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Théo Monnom on 30/08/2022.
|
||||
//
|
||||
|
||||
|
||||
#ifndef RUST_TYPES_H
|
||||
#define RUST_TYPES_H
|
||||
|
||||
#include "api/peer_connection_interface.h"
|
||||
|
||||
namespace livekit {
|
||||
struct RTCConfiguration;
|
||||
struct PeerConnectionObserverWrapper;
|
||||
struct CreateSdpObserverWrapper;
|
||||
struct SetLocalSdpObserverWrapper;
|
||||
struct SetRemoteSdpObserverWrapper;
|
||||
|
||||
// Shared types
|
||||
struct RTCOfferAnswerOptions;
|
||||
}
|
||||
|
||||
#endif //RUST_TYPES_H
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#include "livekit/candidate.h"
|
||||
|
||||
namespace livekit {
|
||||
Candidate::Candidate(const cricket::Candidate &candidate) : candidate_(candidate) {
|
||||
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,12 @@
|
||||
use cxx::UniquePtr;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/candidate.h");
|
||||
|
||||
type Candidate; // cricket::Candidate
|
||||
|
||||
fn _unique_candidate() -> UniquePtr<Candidate>; // Ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#include "livekit/data_channel.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
DataChannel::DataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) : data_channel_(data_channel) {
|
||||
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,12 @@
|
||||
use cxx::UniquePtr;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/data_channel.h");
|
||||
|
||||
type DataChannel;
|
||||
|
||||
fn _unique_data_channel() -> UniquePtr<DataChannel>; // Ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "livekit/jsep.h"
|
||||
#include "libwebrtc-sys/src/jsep.rs.h"
|
||||
#include "api/make_ref_counted.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
IceCandidate::IceCandidate(std::unique_ptr<webrtc::IceCandidateInterface> ice_candidate) : ice_candidate_(std::move(ice_candidate)){
|
||||
|
||||
}
|
||||
|
||||
SessionDescription::SessionDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> session_description) : session_description_(std::move(session_description)){
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<SessionDescription> SessionDescription::clone() const {
|
||||
return std::make_unique<SessionDescription>(session_description_->Clone());
|
||||
}
|
||||
|
||||
std::unique_ptr<webrtc::SessionDescriptionInterface> SessionDescription::release() {
|
||||
return std::move(session_description_);
|
||||
}
|
||||
|
||||
// CreateSdpObserver
|
||||
|
||||
NativeCreateSdpObserver::NativeCreateSdpObserver(
|
||||
rust::Box<CreateSdpObserverWrapper> observer) : observer_(std::move(observer)) {
|
||||
|
||||
}
|
||||
|
||||
void NativeCreateSdpObserver::OnSuccess(webrtc::SessionDescriptionInterface *desc) {
|
||||
// We have ownership of desc
|
||||
observer_->on_success(std::make_unique<SessionDescription>(std::unique_ptr<webrtc::SessionDescriptionInterface>(desc)));
|
||||
}
|
||||
|
||||
void NativeCreateSdpObserver::OnFailure(webrtc::RTCError error) {
|
||||
observer_->on_failure(std::make_unique<RTCError>(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeCreateSdpObserverHandle> create_native_create_sdp_observer(rust::Box<CreateSdpObserverWrapper> observer){
|
||||
return std::make_unique<NativeCreateSdpObserverHandle>(NativeCreateSdpObserverHandle {
|
||||
rtc::make_ref_counted<NativeCreateSdpObserver>(std::move(observer))
|
||||
});
|
||||
}
|
||||
|
||||
// SetLocalSdpObserver
|
||||
|
||||
NativeSetLocalSdpObserver::NativeSetLocalSdpObserver(rust::Box<SetLocalSdpObserverWrapper> observer) : observer_(std::move(observer)) {
|
||||
|
||||
}
|
||||
|
||||
void NativeSetLocalSdpObserver::OnSetLocalDescriptionComplete(webrtc::RTCError error) {
|
||||
observer_->on_set_local_description_complete(std::make_unique<RTCError>(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeSetLocalSdpObserverHandle> create_native_set_local_sdp_observer(rust::Box<SetLocalSdpObserverWrapper> observer){
|
||||
return std::make_unique<NativeSetLocalSdpObserverHandle>(NativeSetLocalSdpObserverHandle {
|
||||
rtc::make_ref_counted<NativeSetLocalSdpObserver>(std::move(observer))
|
||||
});
|
||||
}
|
||||
|
||||
// SetRemoteSdpObserver
|
||||
|
||||
NativeSetRemoteSdpObserver::NativeSetRemoteSdpObserver(rust::Box<SetRemoteSdpObserverWrapper> observer) : observer_(std::move(observer)) {
|
||||
|
||||
}
|
||||
|
||||
void NativeSetRemoteSdpObserver::OnSetRemoteDescriptionComplete(webrtc::RTCError error) {
|
||||
observer_->on_set_remote_description_complete(std::make_unique<RTCError>(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeSetRemoteSdpObserverHandle> create_native_set_remote_sdp_observer(rust::Box<SetRemoteSdpObserverWrapper> observer){
|
||||
return std::make_unique<NativeSetRemoteSdpObserverHandle>(NativeSetRemoteSdpObserverHandle {
|
||||
rtc::make_ref_counted<NativeSetRemoteSdpObserver>(std::move(observer))
|
||||
});
|
||||
}
|
||||
|
||||
} // livekit
|
||||
@@ -0,0 +1,109 @@
|
||||
use cxx::UniquePtr;
|
||||
use cxx::{type_id, ExternType};
|
||||
|
||||
use crate::rtc_error::ffi::RTCError;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
extern "Rust" {
|
||||
type CreateSdpObserverWrapper;
|
||||
fn on_success(self: &CreateSdpObserverWrapper, session_description: UniquePtr<SessionDescription>);
|
||||
fn on_failure(self: &CreateSdpObserverWrapper, error: UniquePtr<RTCError>);
|
||||
|
||||
type SetLocalSdpObserverWrapper;
|
||||
fn on_set_local_description_complete(self: &SetLocalSdpObserverWrapper, error: UniquePtr<RTCError>);
|
||||
|
||||
type SetRemoteSdpObserverWrapper;
|
||||
fn on_set_remote_description_complete(self: &SetRemoteSdpObserverWrapper, error: UniquePtr<RTCError>);
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/jsep.h");
|
||||
include!("livekit/rtc_error.h");
|
||||
|
||||
type RTCError = crate::rtc_error::ffi::RTCError;
|
||||
type IceCandidate;
|
||||
type SessionDescription;
|
||||
type NativeCreateSdpObserverHandle;
|
||||
type NativeSetLocalSdpObserverHandle;
|
||||
type NativeSetRemoteSdpObserverHandle;
|
||||
|
||||
fn create_native_create_sdp_observer(observer: Box<CreateSdpObserverWrapper>) -> UniquePtr<NativeCreateSdpObserverHandle>;
|
||||
fn create_native_set_local_sdp_observer(observer: Box<SetLocalSdpObserverWrapper>) -> UniquePtr<NativeSetLocalSdpObserverHandle>;
|
||||
fn create_native_set_remote_sdp_observer(observer: Box<SetRemoteSdpObserverWrapper>) -> UniquePtr<NativeSetRemoteSdpObserverHandle>;
|
||||
|
||||
fn _unique_ice_candidate() -> UniquePtr<IceCandidate>; // Ignore
|
||||
fn _unique_session_description() -> UniquePtr<SessionDescription>; // Ignore
|
||||
}
|
||||
}
|
||||
|
||||
// CreateSdpObserver
|
||||
|
||||
pub trait CreateSdpObserver: Send + Sync {
|
||||
fn on_success(&self, session_description: UniquePtr<ffi::SessionDescription>);
|
||||
fn on_failure(&self, error: UniquePtr<RTCError>);
|
||||
}
|
||||
|
||||
pub struct CreateSdpObserverWrapper {
|
||||
observer: Box<dyn CreateSdpObserver>,
|
||||
}
|
||||
|
||||
impl CreateSdpObserverWrapper {
|
||||
pub fn new(observer: Box<dyn CreateSdpObserver>) -> Self {
|
||||
Self {
|
||||
observer
|
||||
}
|
||||
}
|
||||
|
||||
fn on_success(&self, session_description: UniquePtr<ffi::SessionDescription>) {
|
||||
self.observer.on_success(session_description);
|
||||
}
|
||||
|
||||
fn on_failure(&self, error: UniquePtr<RTCError>) {
|
||||
self.observer.on_failure(error);
|
||||
}
|
||||
}
|
||||
|
||||
// SetLocalSdpObserver
|
||||
|
||||
pub trait SetLocalSdpObserver: Send + Sync {
|
||||
fn on_set_local_description_complete(&self, error: UniquePtr<RTCError>);
|
||||
}
|
||||
|
||||
pub struct SetLocalSdpObserverWrapper {
|
||||
observer: Box<dyn SetLocalSdpObserver>,
|
||||
}
|
||||
|
||||
impl SetLocalSdpObserverWrapper {
|
||||
pub fn new(observer: Box<dyn SetLocalSdpObserver>) -> Self {
|
||||
Self {
|
||||
observer
|
||||
}
|
||||
}
|
||||
|
||||
fn on_set_local_description_complete(&self, error: UniquePtr<RTCError>) {
|
||||
self.observer.on_set_local_description_complete(error);
|
||||
}
|
||||
}
|
||||
|
||||
// SetRemoteSdpObserver
|
||||
|
||||
pub trait SetRemoteSdpObserver: Send + Sync {
|
||||
fn on_set_remote_description_complete(&self, error: UniquePtr<RTCError>);
|
||||
}
|
||||
|
||||
pub struct SetRemoteSdpObserverWrapper {
|
||||
observer: Box<dyn SetRemoteSdpObserver>,
|
||||
}
|
||||
|
||||
impl SetRemoteSdpObserverWrapper {
|
||||
pub fn new(observer: Box<dyn SetRemoteSdpObserver>) -> Self {
|
||||
Self {
|
||||
observer
|
||||
}
|
||||
}
|
||||
|
||||
fn on_set_remote_description_complete(&self, error: UniquePtr<RTCError>) {
|
||||
self.observer.on_set_remote_description_complete(error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
pub mod media_stream_interface;
|
||||
pub mod peer_connection;
|
||||
pub mod peer_connection_factory;
|
||||
pub mod data_channel;
|
||||
pub mod jsep;
|
||||
pub mod candidate;
|
||||
pub mod rtp_receiver;
|
||||
pub mod rtp_transceiver;
|
||||
pub mod rtc_error;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by Théo Monnom on 31/08/2022.
|
||||
//
|
||||
|
||||
#include "livekit/media_stream_interface.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
MediaStreamInterface::MediaStreamInterface(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) : media_stream_(stream) {
|
||||
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,13 @@
|
||||
use cxx::UniquePtr;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/media_stream_interface.h");
|
||||
|
||||
type MediaStreamInterface;
|
||||
|
||||
fn _unique_media_stream() -> UniquePtr<MediaStreamInterface>; // Ignore
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// Created by Théo Monnom on 30/08/2022.
|
||||
//
|
||||
|
||||
#include "livekit/peer_connection.h"
|
||||
#include "libwebrtc-sys/src/peer_connection.rs.h"
|
||||
|
||||
namespace livekit {
|
||||
|
||||
inline webrtc::PeerConnectionInterface::RTCOfferAnswerOptions toNativeOfferAnswerOptions(const RTCOfferAnswerOptions& options) {
|
||||
webrtc::PeerConnectionInterface::RTCOfferAnswerOptions rtc_options;
|
||||
rtc_options.offer_to_receive_video = options.offer_to_receive_video;
|
||||
rtc_options.offer_to_receive_audio = options.offer_to_receive_audio;
|
||||
rtc_options.voice_activity_detection = options.voice_activity_detection;
|
||||
rtc_options.ice_restart = options.ice_restart;
|
||||
rtc_options.use_rtp_mux = options.use_rtp_mux;
|
||||
rtc_options.raw_packetization_for_video = options.raw_packetization_for_video;
|
||||
rtc_options.num_simulcast_layers = options.num_simulcast_layers;
|
||||
rtc_options.use_obsolete_sctp_sdp = options.use_obsolete_sctp_sdp;
|
||||
return rtc_options;
|
||||
}
|
||||
|
||||
PeerConnection::PeerConnection(rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection,
|
||||
std::unique_ptr<NativePeerConnectionObserver> observer) : peer_connection_(
|
||||
std::move(peer_connection)), observer_(std::move(observer)) {
|
||||
|
||||
}
|
||||
|
||||
void PeerConnection::close() {
|
||||
peer_connection_->Close();
|
||||
}
|
||||
|
||||
void PeerConnection::create_offer(std::unique_ptr<NativeCreateSdpObserverHandle> observer_handle, RTCOfferAnswerOptions options) {
|
||||
peer_connection_->CreateOffer(observer_handle->observer.get(), toNativeOfferAnswerOptions(options));
|
||||
}
|
||||
|
||||
void PeerConnection::create_answer(std::unique_ptr<NativeCreateSdpObserverHandle> observer_handle, RTCOfferAnswerOptions options) {
|
||||
peer_connection_->CreateAnswer(observer_handle->observer.get(), toNativeOfferAnswerOptions(options));
|
||||
}
|
||||
|
||||
void PeerConnection::set_local_description(std::unique_ptr<SessionDescription> desc, std::unique_ptr<NativeSetLocalSdpObserverHandle> observer) {
|
||||
peer_connection_->SetLocalDescription(desc->clone()->release(), observer->observer);
|
||||
}
|
||||
|
||||
void PeerConnection::set_remote_description(std::unique_ptr<SessionDescription> desc, std::unique_ptr<NativeSetRemoteSdpObserverHandle> observer) {
|
||||
peer_connection_->SetRemoteDescription(desc->clone()->release(), observer->observer);
|
||||
}
|
||||
|
||||
/* Observer */
|
||||
|
||||
NativePeerConnectionObserver::NativePeerConnectionObserver(rust::Box<PeerConnectionObserverWrapper> observer) : observer_(std::move(observer)) {
|
||||
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) {
|
||||
observer_->on_signaling_change(static_cast<SignalingState>(new_state));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
||||
observer_->on_add_stream(std::make_unique<MediaStreamInterface>(stream));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface> stream) {
|
||||
observer_->on_remove_stream(std::make_unique<MediaStreamInterface>(stream));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
|
||||
observer_->on_data_channel(std::make_unique<DataChannel>(data_channel));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnRenegotiationNeeded() {
|
||||
observer_->on_renegotiation_needed();
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnNegotiationNeededEvent(uint32_t event_id) {
|
||||
observer_->on_negotiation_needed_event(event_id);
|
||||
}
|
||||
|
||||
void
|
||||
NativePeerConnectionObserver::OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
||||
observer_->on_ice_connection_change(static_cast<IceConnectionState>(new_state));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnStandardizedIceConnectionChange(
|
||||
webrtc::PeerConnectionInterface::IceConnectionState new_state) {
|
||||
observer_->on_standardized_ice_connection_change(static_cast<IceConnectionState>(new_state));
|
||||
}
|
||||
|
||||
void
|
||||
NativePeerConnectionObserver::OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
|
||||
observer_->on_connection_change(static_cast<PeerConnectionState>(new_state));
|
||||
}
|
||||
|
||||
void
|
||||
NativePeerConnectionObserver::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) {
|
||||
observer_->on_ice_gathering_change(static_cast<IceGatheringState>(new_state));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnIceCandidate(const webrtc::IceCandidateInterface *candidate) {
|
||||
auto new_candidate = webrtc::CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(),
|
||||
candidate->candidate());
|
||||
observer_->on_ice_candidate(std::make_unique<IceCandidate>(std::move(new_candidate)));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnIceCandidateError(const std::string &address, int port, const std::string &url,
|
||||
int error_code, const std::string &error_text) {
|
||||
observer_->on_ice_candidate_error(address, port, url, error_code, error_text);
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnIceCandidatesRemoved(const std::vector<cricket::Candidate> &candidates) {
|
||||
rust::Vec<CandidatePtr> vec;
|
||||
|
||||
for (const auto &item: candidates) {
|
||||
vec.push_back(CandidatePtr{
|
||||
std::make_unique<Candidate>(item)
|
||||
});
|
||||
}
|
||||
|
||||
observer_->on_ice_candidates_removed(std::move(vec));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnIceConnectionReceivingChange(bool receiving) {
|
||||
observer_->on_ice_connection_receiving_change(receiving);
|
||||
}
|
||||
|
||||
void
|
||||
NativePeerConnectionObserver::OnIceSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent &event) {
|
||||
CandidatePairChangeEvent e;
|
||||
e.selected_candidate_pair.local = std::make_unique<Candidate>(event.selected_candidate_pair.local);
|
||||
e.selected_candidate_pair.remote = std::make_unique<Candidate>(event.selected_candidate_pair.remote);
|
||||
e.last_data_received_ms = event.last_data_received_ms;
|
||||
e.reason = event.reason;
|
||||
e.estimated_disconnected_time_ms = event.estimated_disconnected_time_ms;
|
||||
|
||||
observer_->on_ice_selected_candidate_pair_changed(std::move(e));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
|
||||
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) {
|
||||
rust::Vec<MediaStreamPtr> vec;
|
||||
|
||||
for (const auto &item: streams) {
|
||||
vec.push_back(MediaStreamPtr{
|
||||
std::make_unique<MediaStreamInterface>(item)
|
||||
});
|
||||
}
|
||||
|
||||
observer_->on_add_track(std::make_unique<RtpReceiver>(receiver), std::move(vec));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) {
|
||||
observer_->on_track(std::make_unique<RtpTransceiver>(transceiver));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
|
||||
observer_->on_remove_track(std::make_unique<RtpReceiver>(receiver));
|
||||
}
|
||||
|
||||
void NativePeerConnectionObserver::OnInterestingUsage(int usage_pattern) {
|
||||
observer_->on_interesting_usage(usage_pattern);
|
||||
}
|
||||
|
||||
std::unique_ptr<NativePeerConnectionObserver> create_native_peer_connection_observer(rust::Box<PeerConnectionObserverWrapper> observer) {
|
||||
return std::make_unique<NativePeerConnectionObserver>(std::move(observer));
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,293 @@
|
||||
use cxx::UniquePtr;
|
||||
use crate::candidate::ffi::Candidate;
|
||||
use crate::data_channel::ffi::DataChannel;
|
||||
use crate::jsep::ffi::IceCandidate;
|
||||
use crate::media_stream_interface::ffi::MediaStreamInterface;
|
||||
use crate::rtp_receiver::ffi::RtpReceiver;
|
||||
use crate::rtp_transceiver::ffi::RtpTransceiver;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
|
||||
struct CandidatePair {
|
||||
local: UniquePtr<Candidate>,
|
||||
remote: UniquePtr<Candidate>,
|
||||
}
|
||||
|
||||
struct CandidatePairChangeEvent {
|
||||
selected_candidate_pair: CandidatePair,
|
||||
last_data_received_ms: i64,
|
||||
reason: String,
|
||||
estimated_disconnected_time_ms: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum PeerConnectionState {
|
||||
kNew,
|
||||
kConnecting,
|
||||
kConnected,
|
||||
kDisconnected,
|
||||
kFailed,
|
||||
kClosed,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum SignalingState {
|
||||
kStable,
|
||||
kHaveLocalOffer,
|
||||
kHaveLocalPrAnswer,
|
||||
kHaveRemoteOffer,
|
||||
kHaveRemotePrAnswer,
|
||||
kClosed,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum IceConnectionState {
|
||||
kIceConnectionNew,
|
||||
kIceConnectionChecking,
|
||||
kIceConnectionConnected,
|
||||
kIceConnectionCompleted,
|
||||
kIceConnectionFailed,
|
||||
kIceConnectionDisconnected,
|
||||
kIceConnectionClosed,
|
||||
kIceConnectionMax,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum IceGatheringState {
|
||||
kIceGatheringNew,
|
||||
kIceGatheringGathering,
|
||||
kIceGatheringComplete
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RTCOfferAnswerOptions {
|
||||
offer_to_receive_video: i32,
|
||||
offer_to_receive_audio: i32,
|
||||
voice_activity_detection: bool,
|
||||
ice_restart: bool,
|
||||
use_rtp_mux: bool,
|
||||
raw_packetization_for_video: bool,
|
||||
num_simulcast_layers: i32,
|
||||
use_obsolete_sctp_sdp: bool,
|
||||
}
|
||||
|
||||
// Wrapper to opaque C++ objects
|
||||
// https://github.com/dtolnay/cxx/issues/741
|
||||
struct MediaStreamPtr {
|
||||
pub ptr: UniquePtr<MediaStreamInterface>
|
||||
}
|
||||
|
||||
struct CandidatePtr {
|
||||
pub ptr: UniquePtr<Candidate>
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/peer_connection.h");
|
||||
include!("livekit/jsep.h");
|
||||
include!("livekit/data_channel.h");
|
||||
include!("livekit/rtp_receiver.h");
|
||||
include!("livekit/rtp_transceiver.h");
|
||||
include!("livekit/media_stream_interface.h");
|
||||
include!("livekit/candidate.h");
|
||||
|
||||
type Candidate = crate::candidate::ffi::Candidate;
|
||||
type IceCandidate = crate::jsep::ffi::IceCandidate;
|
||||
type DataChannel = crate::data_channel::ffi::DataChannel;
|
||||
type RtpReceiver = crate::rtp_receiver::ffi::RtpReceiver;
|
||||
type RtpTransceiver = crate::rtp_transceiver::ffi::RtpTransceiver;
|
||||
type MediaStreamInterface = crate::media_stream_interface::ffi::MediaStreamInterface;
|
||||
type NativeCreateSdpObserverHandle = crate::jsep::ffi::NativeCreateSdpObserverHandle;
|
||||
type NativeSetLocalSdpObserverHandle = crate::jsep::ffi::NativeSetLocalSdpObserverHandle;
|
||||
type NativeSetRemoteSdpObserverHandle = crate::jsep::ffi::NativeSetRemoteSdpObserverHandle;
|
||||
type SessionDescription = crate::jsep::ffi::SessionDescription;
|
||||
|
||||
type NativePeerConnectionObserver;
|
||||
type PeerConnection;
|
||||
|
||||
fn create_offer(self: Pin<&mut PeerConnection>, observer: UniquePtr<NativeCreateSdpObserverHandle>, options: RTCOfferAnswerOptions);
|
||||
fn create_answer(self: Pin<&mut PeerConnection>, observer: UniquePtr<NativeCreateSdpObserverHandle>, options: RTCOfferAnswerOptions);
|
||||
fn set_local_description(self: Pin<&mut PeerConnection>, desc: UniquePtr<SessionDescription>, observer: UniquePtr<NativeSetLocalSdpObserverHandle>);
|
||||
fn set_remote_description(self: Pin<&mut PeerConnection>, desc: UniquePtr<SessionDescription>, observer: UniquePtr<NativeSetRemoteSdpObserverHandle>);
|
||||
fn close(self: Pin<&mut PeerConnection>);
|
||||
|
||||
fn create_native_peer_connection_observer(observer: Box<PeerConnectionObserverWrapper>) -> UniquePtr<NativePeerConnectionObserver>;
|
||||
|
||||
fn _unique_peer_connection() -> UniquePtr<PeerConnection>; // Ignore
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type PeerConnectionObserverWrapper;
|
||||
|
||||
fn on_signaling_change(self: &mut PeerConnectionObserverWrapper, new_state: SignalingState);
|
||||
fn on_add_stream(self: &mut PeerConnectionObserverWrapper, stream: UniquePtr<MediaStreamInterface>);
|
||||
fn on_remove_stream(self: &mut PeerConnectionObserverWrapper, stream: UniquePtr<MediaStreamInterface>);
|
||||
fn on_data_channel(self: &mut PeerConnectionObserverWrapper, data_channel: UniquePtr<DataChannel>);
|
||||
fn on_renegotiation_needed(self: &mut PeerConnectionObserverWrapper);
|
||||
fn on_negotiation_needed_event(self: &mut PeerConnectionObserverWrapper, event: u32);
|
||||
fn on_ice_connection_change(self: &mut PeerConnectionObserverWrapper, new_state: IceConnectionState);
|
||||
fn on_standardized_ice_connection_change(self: &mut PeerConnectionObserverWrapper, new_state: IceConnectionState);
|
||||
fn on_connection_change(self: &mut PeerConnectionObserverWrapper, new_state: PeerConnectionState);
|
||||
fn on_ice_gathering_change(self: &mut PeerConnectionObserverWrapper, new_state: IceGatheringState);
|
||||
fn on_ice_candidate(self: &mut PeerConnectionObserverWrapper, candidate: UniquePtr<IceCandidate>);
|
||||
fn on_ice_candidate_error(self: &mut PeerConnectionObserverWrapper, address: String, port: i32, url: String, error_code: i32, error_text: String);
|
||||
fn on_ice_candidates_removed(self: &mut PeerConnectionObserverWrapper, removed: Vec<CandidatePtr>);
|
||||
fn on_ice_connection_receiving_change(self: &mut PeerConnectionObserverWrapper, receiving: bool);
|
||||
fn on_ice_selected_candidate_pair_changed(self: &mut PeerConnectionObserverWrapper, event: CandidatePairChangeEvent);
|
||||
fn on_add_track(self: &mut PeerConnectionObserverWrapper, receiver: UniquePtr<RtpReceiver>, streams: Vec<MediaStreamPtr>);
|
||||
fn on_track(self: &mut PeerConnectionObserverWrapper, transceiver: UniquePtr<RtpTransceiver>);
|
||||
fn on_remove_track(self: &mut PeerConnectionObserverWrapper, receiver: UniquePtr<RtpReceiver>);
|
||||
fn on_interesting_usage(self: &mut PeerConnectionObserverWrapper, usage_pattern: i32);
|
||||
}
|
||||
}
|
||||
|
||||
// https://webrtc.github.io/webrtc-org/native-code/native-apis/
|
||||
unsafe impl Sync for ffi::PeerConnection {}
|
||||
unsafe impl Send for ffi::PeerConnection {}
|
||||
|
||||
impl Default for ffi::RTCOfferAnswerOptions {
|
||||
/*
|
||||
static const int kUndefined = -1;
|
||||
static const int kMaxOfferToReceiveMedia = 1;
|
||||
static const int kOfferToReceiveMediaTrue = 1;
|
||||
*/
|
||||
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offer_to_receive_video: -1,
|
||||
offer_to_receive_audio: -1,
|
||||
voice_activity_detection: true,
|
||||
ice_restart: false,
|
||||
use_rtp_mux: true,
|
||||
raw_packetization_for_video: false,
|
||||
num_simulcast_layers: 1,
|
||||
use_obsolete_sctp_sdp: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PeerConnectionObserver: Send + Sync {
|
||||
fn on_signaling_change(&mut self, new_state: ffi::SignalingState);
|
||||
fn on_add_stream(&mut self, stream: UniquePtr<MediaStreamInterface>);
|
||||
fn on_remove_stream(&mut self, stream: UniquePtr<MediaStreamInterface>);
|
||||
fn on_data_channel(&mut self, data_channel: UniquePtr<DataChannel>);
|
||||
fn on_renegotiation_needed(&mut self);
|
||||
fn on_negotiation_needed_event(&mut self, event: u32);
|
||||
fn on_ice_connection_change(&mut self, new_state: ffi::IceConnectionState);
|
||||
fn on_standardized_ice_connection_change(&mut self, new_state: ffi::IceConnectionState);
|
||||
fn on_connection_change(&mut self, new_state: ffi::PeerConnectionState);
|
||||
fn on_ice_gathering_change(&mut self, new_state: ffi::IceGatheringState);
|
||||
fn on_ice_candidate(&mut self, candidate: UniquePtr<IceCandidate>);
|
||||
fn on_ice_candidate_error(&mut self, address: String, port: i32, url: String, error_code: i32, error_text: String);
|
||||
fn on_ice_candidates_removed(&mut self, removed: Vec<UniquePtr<Candidate>>);
|
||||
fn on_ice_connection_receiving_change(&mut self, receiving: bool);
|
||||
fn on_ice_selected_candidate_pair_changed(&mut self, event: ffi::CandidatePairChangeEvent);
|
||||
fn on_add_track(&mut self, receiver: UniquePtr<RtpReceiver>, streams: Vec<UniquePtr<MediaStreamInterface>>);
|
||||
fn on_track(&mut self, transceiver: UniquePtr<RtpTransceiver>);
|
||||
fn on_remove_track(&mut self, receiver: UniquePtr<RtpReceiver>);
|
||||
fn on_interesting_usage(&mut self, usage_pattern: i32);
|
||||
}
|
||||
|
||||
pub struct PeerConnectionObserverWrapper {
|
||||
observer: Box<dyn PeerConnectionObserver>,
|
||||
}
|
||||
|
||||
impl PeerConnectionObserverWrapper {
|
||||
pub fn new(observer: Box<dyn PeerConnectionObserver>) -> Self {
|
||||
Self {
|
||||
observer
|
||||
}
|
||||
}
|
||||
|
||||
fn on_signaling_change(&mut self, new_state: ffi::SignalingState) {
|
||||
self.observer.on_signaling_change(new_state);
|
||||
}
|
||||
|
||||
fn on_add_stream(&mut self, stream: UniquePtr<MediaStreamInterface>) {
|
||||
self.observer.on_add_stream(stream);
|
||||
}
|
||||
|
||||
fn on_remove_stream(&mut self, stream: UniquePtr<MediaStreamInterface>) {
|
||||
self.observer.on_remove_stream(stream);
|
||||
}
|
||||
|
||||
fn on_data_channel(&mut self, data_channel: UniquePtr<DataChannel>) {
|
||||
self.observer.on_data_channel(data_channel);
|
||||
}
|
||||
|
||||
fn on_renegotiation_needed(&mut self) {
|
||||
self.observer.on_renegotiation_needed();
|
||||
}
|
||||
|
||||
fn on_negotiation_needed_event(&mut self, event: u32) {
|
||||
self.observer.on_negotiation_needed_event(event);
|
||||
}
|
||||
|
||||
fn on_ice_connection_change(&mut self, new_state: ffi::IceConnectionState) {
|
||||
self.observer.on_ice_connection_change(new_state);
|
||||
}
|
||||
|
||||
fn on_standardized_ice_connection_change(&mut self, new_state: ffi::IceConnectionState) {
|
||||
self.observer.on_standardized_ice_connection_change(new_state);
|
||||
}
|
||||
|
||||
fn on_connection_change(&mut self, new_state: ffi::PeerConnectionState) {
|
||||
self.observer.on_connection_change(new_state);
|
||||
}
|
||||
|
||||
fn on_ice_gathering_change(&mut self, new_state: ffi::IceGatheringState) {
|
||||
self.observer.on_ice_gathering_change(new_state);
|
||||
}
|
||||
|
||||
fn on_ice_candidate(&mut self, candidate: UniquePtr<IceCandidate>) {
|
||||
self.observer.on_ice_candidate(candidate);
|
||||
}
|
||||
|
||||
fn on_ice_candidate_error(&mut self, address: String, port: i32, url: String, error_code: i32, error_text: String) {
|
||||
self.observer.on_ice_candidate_error(address, port, url, error_code, error_text);
|
||||
}
|
||||
|
||||
fn on_ice_candidates_removed(&mut self, removed: Vec<ffi::CandidatePtr>) {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
for v in removed {
|
||||
vec.push(v.ptr);
|
||||
}
|
||||
|
||||
self.observer.on_ice_candidates_removed(vec);
|
||||
}
|
||||
|
||||
fn on_ice_connection_receiving_change(&mut self, receiving: bool) {
|
||||
self.observer.on_ice_connection_receiving_change(receiving);
|
||||
}
|
||||
|
||||
fn on_ice_selected_candidate_pair_changed(&mut self, event: ffi::CandidatePairChangeEvent) {
|
||||
self.observer.on_ice_selected_candidate_pair_changed(event);
|
||||
}
|
||||
|
||||
fn on_add_track(&mut self, receiver: UniquePtr<RtpReceiver>, streams: Vec<ffi::MediaStreamPtr>) {
|
||||
let mut vec = Vec::new();
|
||||
|
||||
for v in streams {
|
||||
vec.push(v.ptr);
|
||||
}
|
||||
|
||||
self.observer.on_add_track(receiver, vec);
|
||||
}
|
||||
|
||||
fn on_track(&mut self, transceiver: UniquePtr<RtpTransceiver>) {
|
||||
self.observer.on_track(transceiver);
|
||||
}
|
||||
|
||||
fn on_remove_track(&mut self, receiver: UniquePtr<RtpReceiver>) {
|
||||
self.observer.on_remove_track(receiver);
|
||||
}
|
||||
|
||||
fn on_interesting_usage(&mut self, usage_pattern: i32) {
|
||||
self.observer.on_interesting_usage(usage_pattern);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// Created by Théo Monnom on 03/08/2022.
|
||||
//
|
||||
|
||||
#include "livekit/peer_connection_factory.h"
|
||||
#include "api/video_codecs/builtin_video_decoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
#include "api/video_codecs/builtin_video_encoder_factory.h"
|
||||
#include "media/engine/webrtc_media_engine.h"
|
||||
#include "api/task_queue/default_task_queue_factory.h"
|
||||
#include "api/rtc_event_log/rtc_event_log_factory.h"
|
||||
#include "libwebrtc-sys/src/peer_connection_factory.rs.h"
|
||||
|
||||
namespace livekit{
|
||||
|
||||
PeerConnectionFactory::PeerConnectionFactory(){
|
||||
rtc::LogMessage::LogToDebug(rtc::LS_INFO);
|
||||
RTC_LOG(LS_INFO) << "PeerConnectionFactory::PeerConnectionFactory()";
|
||||
|
||||
network_thread_ = rtc::Thread::CreateWithSocketServer();
|
||||
network_thread_->SetName("network_thread", &network_thread_);
|
||||
network_thread_->Start();
|
||||
worker_thread_ = rtc::Thread::Create();
|
||||
worker_thread_->SetName("worker_thread", &worker_thread_);
|
||||
worker_thread_->Start();
|
||||
signaling_thread_ = rtc::Thread::Create();
|
||||
signaling_thread_->SetName("signaling_thread", &signaling_thread_);
|
||||
signaling_thread_->Start();
|
||||
|
||||
webrtc::PeerConnectionFactoryDependencies dependencies;
|
||||
dependencies.network_thread = network_thread_.get();
|
||||
dependencies.worker_thread = worker_thread_.get();
|
||||
dependencies.signaling_thread = signaling_thread_.get();
|
||||
dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory();
|
||||
dependencies.event_log_factory = std::make_unique<webrtc::RtcEventLogFactory>(dependencies.task_queue_factory.get());
|
||||
|
||||
cricket::MediaEngineDependencies media_deps;
|
||||
media_deps.task_queue_factory = dependencies.task_queue_factory.get();
|
||||
media_deps.video_encoder_factory = webrtc::CreateBuiltinVideoEncoderFactory();
|
||||
media_deps.video_decoder_factory = webrtc::CreateBuiltinVideoDecoderFactory();
|
||||
media_deps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
|
||||
media_deps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
|
||||
|
||||
dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps));
|
||||
|
||||
peer_factory_ = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies));
|
||||
|
||||
if (peer_factory_.get() == nullptr) {
|
||||
RTC_LOG_ERR(LS_ERROR) << "Failed to create PeerConnectionFactory";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerConnection> PeerConnectionFactory::create_peer_connection(std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config, std::unique_ptr<NativePeerConnectionObserver> observer) const {
|
||||
webrtc::PeerConnectionDependencies deps{observer.get()};
|
||||
auto result = peer_factory_->CreatePeerConnectionOrError(*config, std::move(deps));
|
||||
|
||||
if(!result.ok()){
|
||||
throw std::runtime_error(result.error().message()); // TODO(theomonnom) Bridge RTCError - Mb use ProtoBuf
|
||||
}
|
||||
|
||||
return std::make_unique<PeerConnection>(std::move(result.value()), std::move(observer));
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerConnectionFactory> create_peer_connection_factory() {
|
||||
return std::make_unique<PeerConnectionFactory>();
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeRTCConfiguration> create_rtc_configuration(RTCConfiguration conf){
|
||||
auto rtc = std::make_unique<webrtc::PeerConnectionInterface::RTCConfiguration>();
|
||||
|
||||
for (auto &item: conf.ice_servers){
|
||||
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||
ice_server.username = item.username.c_str();
|
||||
ice_server.password = item.password.c_str();
|
||||
|
||||
for (auto &url: item.urls){
|
||||
ice_server.urls.push_back(url.c_str());
|
||||
}
|
||||
|
||||
rtc->servers.push_back(ice_server);
|
||||
}
|
||||
|
||||
return rtc;
|
||||
}
|
||||
} // namespace lk
|
||||
@@ -0,0 +1,186 @@
|
||||
use std::any::Any;
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
use cxx::UniquePtr;
|
||||
use log::info;
|
||||
use crate::candidate::ffi::Candidate;
|
||||
use crate::data_channel::ffi::DataChannel;
|
||||
use crate::jsep::ffi::IceCandidate;
|
||||
use crate::media_stream_interface::ffi::MediaStreamInterface;
|
||||
use crate::{jsep, peer_connection};
|
||||
use crate::jsep::CreateSdpObserver;
|
||||
use crate::peer_connection::ffi::{CandidatePairChangeEvent, IceConnectionState, IceGatheringState, PeerConnectionState, SignalingState};
|
||||
use crate::peer_connection::PeerConnectionObserver;
|
||||
use crate::rtp_receiver::ffi::RtpReceiver;
|
||||
use crate::rtp_transceiver::ffi::RtpTransceiver;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ICEServer {
|
||||
urls: Vec<String>,
|
||||
username: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RTCConfiguration {
|
||||
pub ice_servers: Vec<ICEServer>,
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/peer_connection_factory.h");
|
||||
|
||||
type PeerConnection = crate::peer_connection::ffi::PeerConnection;
|
||||
type NativePeerConnectionObserver = crate::peer_connection::ffi::NativePeerConnectionObserver;
|
||||
type PeerConnectionFactory;
|
||||
type NativeRTCConfiguration;
|
||||
|
||||
fn create_peer_connection_factory() -> UniquePtr<PeerConnectionFactory>;
|
||||
fn create_rtc_configuration(conf: RTCConfiguration) -> UniquePtr<NativeRTCConfiguration>;
|
||||
|
||||
unsafe fn create_peer_connection(self: &PeerConnectionFactory, config: UniquePtr<NativeRTCConfiguration>, observer: UniquePtr<NativePeerConnectionObserver>) -> Result<UniquePtr<PeerConnection>>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
struct TestObserver {
|
||||
|
||||
}
|
||||
|
||||
impl PeerConnectionObserver for TestObserver {
|
||||
fn on_signaling_change(&self, new_state: SignalingState) {
|
||||
log::debug!("Signaling state changed: {:?}", new_state);
|
||||
}
|
||||
|
||||
fn on_add_stream(&self, stream: UniquePtr<MediaStreamInterface>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_remove_stream(&self, stream: UniquePtr<MediaStreamInterface>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_data_channel(&self, data_channel: UniquePtr<DataChannel>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_renegotiation_needed(&self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_negotiation_needed_event(&self, event: u32) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_ice_connection_change(&self, new_state: IceConnectionState) {
|
||||
log::debug!("ICE connection state changed: {:?}", new_state);
|
||||
}
|
||||
|
||||
fn on_standardized_ice_connection_change(&self, new_state: IceConnectionState) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_connection_change(&self, new_state: PeerConnectionState) {
|
||||
log::debug!("PeerConnection state changed: {:?}", new_state);
|
||||
}
|
||||
|
||||
fn on_ice_gathering_change(&self, new_state: IceGatheringState) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_ice_candidate(&self, candidate: UniquePtr<IceCandidate>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_ice_candidate_error(&self, address: String, port: i32, url: String, error_code: i32, error_text: String) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_ice_candidates_removed(&self, removed: Vec<UniquePtr<Candidate>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_ice_connection_receiving_change(&self, receiving: bool) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_ice_selected_candidate_pair_changed(&self, event: CandidatePairChangeEvent) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_add_track(&self, receiver: UniquePtr<RtpReceiver>, streams: Vec<UniquePtr<MediaStreamInterface>>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_track(&self, transceiver: UniquePtr<RtpTransceiver>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_remove_track(&self, receiver: UniquePtr<RtpReceiver>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn on_interesting_usage(&self, usage_pattern: i32) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
struct SessionObserver {
|
||||
|
||||
}
|
||||
|
||||
impl CreateSdpObserver for SessionObserver {
|
||||
fn on_success(&self, session_description: UniquePtr<crate::jsep::ffi::SessionDescription>) {
|
||||
info!("on_success");
|
||||
}
|
||||
|
||||
fn on_failure(&self, error: UniquePtr<crate::rtc_error::ffi::RTCError>) {
|
||||
info!("on_failure");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_pc_test() {
|
||||
env_logger::init();
|
||||
let factory = ffi::create_peer_connection_factory(); // Default factory config is defined on the c++ side atm
|
||||
unsafe {
|
||||
let mut pc = factory.create_peer_connection(ffi::create_rtc_configuration(ffi::RTCConfiguration {
|
||||
ice_servers: vec![ffi::ICEServer {
|
||||
urls: vec!["stun:stun.l.google.com:19302".to_string()],
|
||||
username: "".to_string(),
|
||||
password: "".to_string(),
|
||||
}],
|
||||
}), peer_connection::ffi::create_native_peer_connection_observer(Box::new(peer_connection::PeerConnectionObserverWrapper::new(Box::new(TestObserver{}))))).unwrap();
|
||||
|
||||
|
||||
let options = peer_connection::ffi::RTCOfferAnswerOptions::default();
|
||||
|
||||
let sdp_observer = jsep::ffi::create_native_create_sdp_observer(Box::new(jsep::CreateSdpObserverWrapper::new(Box::new(SessionObserver{}))));
|
||||
pc.pin_mut().create_offer(sdp_observer, options);
|
||||
|
||||
sleep(Duration::from_secs(2));
|
||||
|
||||
pc.pin_mut().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by theom on 04/09/2022.
|
||||
//
|
||||
|
||||
#include "livekit/rtc_error.h"
|
||||
|
||||
namespace livekit {
|
||||
RTCError::RTCError(webrtc::RTCError error) : rtc_error_(std::move(error)) {
|
||||
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
// TODO(theomonnom) Don't use RTCError as Opaque. I should use a Struct and serialize/deserialize when needed for Result<>
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/rtc_error.h");
|
||||
|
||||
type RTCError;
|
||||
|
||||
fn _unique_rtc_error() -> UniquePtr<RTCError>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by Théo Monnom on 01/09/2022.
|
||||
//
|
||||
|
||||
#include "livekit/rtp_receiver.h"
|
||||
|
||||
namespace livekit {
|
||||
RtpReceiver::RtpReceiver(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) : receiver_(std::move(receiver)) {
|
||||
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,12 @@
|
||||
use cxx::UniquePtr;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/rtp_receiver.h");
|
||||
|
||||
type RtpReceiver;
|
||||
|
||||
fn _unique_rtp_receiver() -> UniquePtr<RtpReceiver>; // Ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Created by Théo Monnom on 02/09/2022.
|
||||
//
|
||||
|
||||
#include "livekit/rtp_transceiver.h"
|
||||
|
||||
namespace livekit {
|
||||
RtpTransceiver::RtpTransceiver(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) : transceiver_(std::move(transceiver)) {
|
||||
|
||||
}
|
||||
} // livekit
|
||||
@@ -0,0 +1,12 @@
|
||||
use cxx::UniquePtr;
|
||||
|
||||
#[cxx::bridge(namespace = "livekit")]
|
||||
pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("livekit/rtp_transceiver.h");
|
||||
|
||||
type RtpTransceiver;
|
||||
|
||||
fn _unique_rtp_transceiver() -> UniquePtr<RtpTransceiver>; // Ignore
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
pub struct DataChannel {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
pub struct IceCandidate {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
pub mod peer_connection_factory;
|
||||
pub mod peer_connection;
|
||||
pub mod rtc_error;
|
||||
pub mod data_channel;
|
||||
pub mod media_stream;
|
||||
pub mod rtp_receiver;
|
||||
pub mod rtp_transceiver;
|
||||
pub mod ice_candidate;
|
||||
pub mod session_description;
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
pub struct MediaStream {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use cxx::UniquePtr;
|
||||
use tokio::sync::mpsc;
|
||||
use libwebrtc_sys::peer_connection as sys_pc;
|
||||
use libwebrtc_sys::jsep as sys_jsep;
|
||||
|
||||
use crate::data_channel::DataChannel;
|
||||
use crate::media_stream::MediaStream;
|
||||
use crate::ice_candidate::IceCandidate;
|
||||
use crate::rtp_receiver::RtpReceiver;
|
||||
use crate::rtp_transceiver::RtpTransceiver;
|
||||
use crate::session_description::SessionDescription;
|
||||
use crate::rtc_error::RTCError;
|
||||
|
||||
pub use libwebrtc_sys::peer_connection::ffi::PeerConnectionState;
|
||||
pub use libwebrtc_sys::peer_connection::ffi::SignalingState;
|
||||
pub use libwebrtc_sys::peer_connection::ffi::IceConnectionState;
|
||||
pub use libwebrtc_sys::peer_connection::ffi::IceGatheringState;
|
||||
pub use libwebrtc_sys::peer_connection::ffi::RTCOfferAnswerOptions;
|
||||
|
||||
pub struct PeerConnection {
|
||||
cxx_handle: UniquePtr<sys_pc::ffi::PeerConnection>,
|
||||
observer: InternalObserver
|
||||
}
|
||||
|
||||
impl PeerConnection {
|
||||
pub fn new(cxx_handle: UniquePtr<sys_pc::ffi::PeerConnection>) -> Self {
|
||||
Self {
|
||||
cxx_handle,
|
||||
observer: InternalObserver {
|
||||
on_signaling_change_handler: Arc::new(Default::default()),
|
||||
on_add_stream_handler: Arc::new(Default::default()),
|
||||
on_remove_stream_handler: Arc::new(Default::default()),
|
||||
on_data_channel_handler: Arc::new(Default::default()),
|
||||
on_renegotiation_needed_handler: Arc::new(Default::default()),
|
||||
on_negotiation_needed_event_handler: Arc::new(Default::default()),
|
||||
on_ice_connection_change_handler: Arc::new(Default::default()),
|
||||
on_standardized_ice_connection_change_handler: Arc::new(Default::default()),
|
||||
on_connection_change_handler: Arc::new(Default::default()),
|
||||
on_ice_gathering_change_handler: Arc::new(Default::default()),
|
||||
on_ice_candidate_handler: Arc::new(Default::default()),
|
||||
on_ice_candidate_error_handler: Arc::new(Default::default()),
|
||||
on_ice_candidates_removed_handler: Arc::new(Default::default()),
|
||||
on_ice_connection_receiving_change_handler: Arc::new(Default::default()),
|
||||
on_ice_selected_candidate_pair_changed_handler: Arc::new(Default::default()),
|
||||
on_add_track_handler: Arc::new(Default::default()),
|
||||
on_track_handler: Arc::new(Default::default()),
|
||||
on_remove_track_handler: Arc::new(Default::default()),
|
||||
on_interesting_usage_handler: Arc::new(Default::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create_offer(&mut self) -> Result<SessionDescription, RTCError> {
|
||||
let (tx, mut rx) = mpsc::channel(1);
|
||||
|
||||
let wrapper = sys_jsep::CreateSdpObserverWrapper::new(Box::new(InternalCreateSdpObserver { tx }));
|
||||
let native_wrapper = sys_jsep::ffi::create_native_create_sdp_observer(Box::new(wrapper));
|
||||
|
||||
self.cxx_handle.pin_mut().create_offer(native_wrapper, RTCOfferAnswerOptions::default());
|
||||
rx.recv().await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn create_answer(&mut self) -> Result<SessionDescription, RTCError> {
|
||||
|
||||
}
|
||||
|
||||
pub fn on_signaling_change(&mut self, handler: OnSignalingChangeHandler) {
|
||||
*self.observer.on_signaling_change_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_add_stream(&mut self, handler: OnAddStreamHandler) {
|
||||
*self.observer.on_add_stream_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_remove_stream(&mut self, handler: OnRemoveStreamHandler) {
|
||||
*self.observer.on_remove_stream_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_data_channel(&mut self, handler: OnDataChannelHandler) {
|
||||
*self.observer.on_data_channel_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_renegotiation_needed(&mut self, handler: OnRenegotiationNeededHandler) {
|
||||
*self.observer.on_renegotiation_needed_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_connection_change(&mut self, handler: OnIceConnectionChangeHandler) {
|
||||
*self.observer.on_ice_connection_change_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_standardized_ice_connection_change(&mut self, handler: OnStandardizedIceConnectionChangeHandler) {
|
||||
*self.observer.on_standardized_ice_connection_change_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_connection_change(&mut self, handler: OnConnectionChangeHandler) {
|
||||
*self.observer.on_connection_change_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_gathering_change(&mut self, handler: OnIceGatheringChangeHandler) {
|
||||
*self.observer.on_ice_gathering_change_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_candidate(&mut self, handler: OnIceCandidateHandler) {
|
||||
*self.observer.on_ice_candidate_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_candidate_error(&mut self, handler: OnIceCandidateErrorHandler) {
|
||||
*self.observer.on_ice_candidate_error_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_candidates_removed(&mut self, handler: OnIceCandidatesRemovedHandler) {
|
||||
*self.observer.on_ice_candidates_removed_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_connection_receiving_change(&mut self, handler: OnIceConnectionReceivingChangeHandler) {
|
||||
*self.observer.on_ice_connection_receiving_change_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_ice_selected_candidate_pair_changed(&mut self, handler: OnIceSelectedCandidatePairChangedHandler) {
|
||||
*self.observer.on_ice_selected_candidate_pair_changed_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_add_track(&mut self, handler: OnAddTrackHandler) {
|
||||
*self.observer.on_add_track_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_track(&mut self, handler: OnTrackHandler) {
|
||||
*self.observer.on_track_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_remove_track(&mut self, handler: OnRemoveTrackHandler) {
|
||||
*self.observer.on_remove_track_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
|
||||
pub fn on_interesting_usage(&mut self, handler: OnInterestingUsageHandler) {
|
||||
*self.observer.on_interesting_usage_handler.lock().unwrap() = Some(handler);
|
||||
}
|
||||
}
|
||||
|
||||
// CreateSdpObserver
|
||||
|
||||
struct InternalCreateSdpObserver {
|
||||
tx: mpsc::Sender<Result<SessionDescription, RTCError>>
|
||||
}
|
||||
|
||||
impl sys_jsep::CreateSdpObserver for InternalCreateSdpObserver {
|
||||
fn on_success(&self, session_description: UniquePtr<libwebrtc_sys::jsep::ffi::SessionDescription>) {
|
||||
self.tx.blocking_send(Ok(SessionDescription{})).unwrap(); // TODO
|
||||
}
|
||||
|
||||
fn on_failure(&self, error: UniquePtr<libwebrtc_sys::rtc_error::ffi::RTCError>) {
|
||||
self.tx.blocking_send(Err(RTCError{})).unwrap(); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
// PeerConnectionObserver
|
||||
|
||||
// TODO(theomonnom) Should we return futures?
|
||||
pub type OnSignalingChangeHandler = Box<dyn FnMut(SignalingState) + Send + Sync>;
|
||||
pub type OnAddStreamHandler = Box<dyn FnMut(MediaStream) + Send + Sync>;
|
||||
pub type OnRemoveStreamHandler = Box<dyn FnMut(MediaStream) + Send + Sync>;
|
||||
pub type OnDataChannelHandler = Box<dyn FnMut(DataChannel) + Send + Sync>;
|
||||
pub type OnRenegotiationNeededHandler = Box<dyn FnMut() + Send + Sync>;
|
||||
pub type OnNegotiationNeededEventHandler = Box<dyn FnMut(u32) + Send + Sync>;
|
||||
pub type OnIceConnectionChangeHandler = Box<dyn FnMut(IceConnectionState) + Send + Sync>;
|
||||
pub type OnStandardizedIceConnectionChangeHandler = Box<dyn FnMut(IceConnectionState) + Send + Sync>;
|
||||
pub type OnConnectionChangeHandler = Box<dyn FnMut(PeerConnectionState) + Send + Sync>;
|
||||
pub type OnIceGatheringChangeHandler = Box<dyn FnMut(IceGatheringState) + Send + Sync>;
|
||||
pub type OnIceCandidateHandler = Box<dyn FnMut(IceCandidate) + Send + Sync>;
|
||||
pub type OnIceCandidateErrorHandler = Box<dyn FnMut(String, i32, String, i32, String) + Send + Sync>;
|
||||
pub type OnIceCandidatesRemovedHandler = Box<dyn FnMut(Vec<IceCandidate>) + Send + Sync>;
|
||||
pub type OnIceConnectionReceivingChangeHandler = Box<dyn FnMut(bool) + Send + Sync>;
|
||||
pub type OnIceSelectedCandidatePairChangedHandler = Box<dyn FnMut(libwebrtc_sys::peer_connection::ffi::CandidatePairChangeEvent) + Send + Sync>;
|
||||
pub type OnAddTrackHandler = Box<dyn FnMut(RtpReceiver, Vec<MediaStream>) + Send + Sync>;
|
||||
pub type OnTrackHandler = Box<dyn FnMut(RtpTransceiver) + Send + Sync>;
|
||||
pub type OnRemoveTrackHandler = Box<dyn FnMut(RtpReceiver) + Send + Sync>;
|
||||
pub type OnInterestingUsageHandler = Box<dyn FnMut(i32) + Send + Sync>;
|
||||
|
||||
struct InternalObserver {
|
||||
on_signaling_change_handler: Arc<Mutex<Option<OnSignalingChangeHandler>>>,
|
||||
on_add_stream_handler: Arc<Mutex<Option<OnAddStreamHandler>>>,
|
||||
on_remove_stream_handler: Arc<Mutex<Option<OnRemoveStreamHandler>>>,
|
||||
on_data_channel_handler: Arc<Mutex<Option<OnDataChannelHandler>>>,
|
||||
on_renegotiation_needed_handler: Arc<Mutex<Option<OnRenegotiationNeededHandler>>>,
|
||||
on_negotiation_needed_event_handler: Arc<Mutex<Option<OnNegotiationNeededEventHandler>>>,
|
||||
on_ice_connection_change_handler: Arc<Mutex<Option<OnIceConnectionChangeHandler>>>,
|
||||
on_standardized_ice_connection_change_handler: Arc<Mutex<Option<OnStandardizedIceConnectionChangeHandler>>>,
|
||||
on_connection_change_handler: Arc<Mutex<Option<OnConnectionChangeHandler>>>,
|
||||
on_ice_gathering_change_handler: Arc<Mutex<Option<OnIceGatheringChangeHandler>>>,
|
||||
on_ice_candidate_handler: Arc<Mutex<Option<OnIceCandidateHandler>>>,
|
||||
on_ice_candidate_error_handler: Arc<Mutex<Option<OnIceCandidateErrorHandler>>>,
|
||||
on_ice_candidates_removed_handler: Arc<Mutex<Option<OnIceCandidatesRemovedHandler>>>,
|
||||
on_ice_connection_receiving_change_handler: Arc<Mutex<Option<OnIceConnectionReceivingChangeHandler>>>,
|
||||
on_ice_selected_candidate_pair_changed_handler: Arc<Mutex<Option<OnIceSelectedCandidatePairChangedHandler>>>,
|
||||
on_add_track_handler: Arc<Mutex<Option<OnAddTrackHandler>>>,
|
||||
on_track_handler: Arc<Mutex<Option<OnTrackHandler>>>,
|
||||
on_remove_track_handler: Arc<Mutex<Option<OnRemoveTrackHandler>>>,
|
||||
on_interesting_usage_handler: Arc<Mutex<Option<OnInterestingUsageHandler>>>
|
||||
}
|
||||
|
||||
// Observers are being called on the Signaling Thread
|
||||
impl sys_pc::PeerConnectionObserver for InternalObserver {
|
||||
fn on_signaling_change(&mut self, new_state: SignalingState) {
|
||||
let mut handler = self.on_signaling_change_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_add_stream(&mut self, stream: UniquePtr<libwebrtc_sys::media_stream_interface::ffi::MediaStreamInterface>) {
|
||||
let mut handler = self.on_add_stream_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_remove_stream(&mut self, stream: UniquePtr<libwebrtc_sys::media_stream_interface::ffi::MediaStreamInterface>) {
|
||||
let mut handler = self.on_remove_stream_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_data_channel(&mut self, data_channel: UniquePtr<libwebrtc_sys::data_channel::ffi::DataChannel>) {
|
||||
let mut handler = self.on_data_channel_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_renegotiation_needed(&mut self) {
|
||||
let mut handler = self.on_renegotiation_needed_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
fn on_negotiation_needed_event(&mut self, event: u32) {
|
||||
let mut handler = self.on_negotiation_needed_event_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(event);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_connection_change(&mut self, new_state: IceConnectionState) {
|
||||
let mut handler = self.on_ice_connection_change_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_standardized_ice_connection_change(&mut self, new_state: IceConnectionState) {
|
||||
let mut handler = self.on_standardized_ice_connection_change_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_connection_change(&mut self, new_state: PeerConnectionState) {
|
||||
let mut handler = self.on_connection_change_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_gathering_change(&mut self, new_state: IceGatheringState) {
|
||||
let mut handler = self.on_ice_gathering_change_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(new_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_candidate(&mut self, candidate: UniquePtr<libwebrtc_sys::jsep::ffi::IceCandidate>) {
|
||||
let mut handler = self.on_ice_candidate_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_candidate_error(&mut self, address: String, port: i32, url: String, error_code: i32, error_text: String) {
|
||||
let mut handler = self.on_ice_candidate_error_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(address, port, url, error_code, error_text);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_candidates_removed(&mut self, removed: Vec<UniquePtr<libwebrtc_sys::candidate::ffi::Candidate>>) {
|
||||
let mut handler = self.on_ice_candidates_removed_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_connection_receiving_change(&mut self, receiving: bool) {
|
||||
let mut handler = self.on_ice_connection_receiving_change_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(receiving);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_ice_selected_candidate_pair_changed(&mut self, event: libwebrtc_sys::peer_connection::ffi::CandidatePairChangeEvent) {
|
||||
let mut handler = self.on_ice_selected_candidate_pair_changed_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(event);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_add_track(&mut self, receiver: UniquePtr<libwebrtc_sys::rtp_receiver::ffi::RtpReceiver>, streams: Vec<UniquePtr<libwebrtc_sys::media_stream_interface::ffi::MediaStreamInterface>>) {
|
||||
let mut handler = self.on_add_track_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_track(&mut self, transceiver: UniquePtr<libwebrtc_sys::rtp_transceiver::ffi::RtpTransceiver>) {
|
||||
let mut handler = self.on_track_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_remove_track(&mut self, receiver: UniquePtr<libwebrtc_sys::rtp_receiver::ffi::RtpReceiver>) {
|
||||
let mut handler = self.on_remove_track_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
// TODO(theomonnom)
|
||||
}
|
||||
}
|
||||
|
||||
fn on_interesting_usage(&mut self, usage_pattern: i32) {
|
||||
let mut handler = self.on_interesting_usage_handler.lock().unwrap();
|
||||
if let Some(f) = handler.as_mut() {
|
||||
f(usage_pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use cxx::UniquePtr;
|
||||
use libwebrtc_sys::peer_connection_factory as sys_factory;
|
||||
use libwebrtc_sys::peer_connection as sys_pc;
|
||||
|
||||
use crate::peer_connection::PeerConnection;
|
||||
use crate::rtc_error::RTCError;
|
||||
|
||||
pub use sys_factory::ffi::{RTCConfiguration, ICEServer};
|
||||
|
||||
pub struct PeerConnectionFactory {
|
||||
cxx_handle: UniquePtr<sys_factory::ffi::PeerConnectionFactory>
|
||||
}
|
||||
|
||||
impl PeerConnectionFactory {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cxx_handle: sys_factory::ffi::create_peer_connection_factory()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_peer_connection(&self, config: RTCConfiguration, observer: Box<dyn sys_pc::PeerConnectionObserver>) -> Result<PeerConnection, RTCError> {
|
||||
let native_config = sys_factory::ffi::create_rtc_configuration(config);
|
||||
let native_observer = sys_pc::ffi::create_native_peer_connection_observer(Box::new(sys_pc::PeerConnectionObserverWrapper::new(observer)));
|
||||
|
||||
let pc_result : Result<UniquePtr<sys_pc::ffi::PeerConnection>, cxx::Exception> = unsafe {
|
||||
self.cxx_handle.create_peer_connection(native_config, native_observer)
|
||||
};
|
||||
|
||||
match pc_result {
|
||||
Ok(cxx_handle) => {
|
||||
let pc = PeerConnection::new(cxx_handle);
|
||||
Ok(pc)
|
||||
}
|
||||
Err(e) => {
|
||||
Err(RTCError{}) // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::peer_connection_factory::PeerConnectionFactory;
|
||||
use crate::peer_connection_factory::{RTCConfiguration, ICEServer};
|
||||
|
||||
#[test]
|
||||
fn create_pc(){
|
||||
let factory = PeerConnectionFactory::new();
|
||||
let pc = factory.create_peer_connection(RTCConfiguration{
|
||||
ice_servers: vec!()
|
||||
}, Box::new(()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RTCError {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
pub struct RtpReceiver {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
pub struct RtpTransceiver {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SessionDescription {
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
|
||||
# For now ( I don't want the libraries to be on GH )
|
||||
app/libs
|
||||
app/src/main/jniLibs
|
||||
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -1,60 +0,0 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk 32
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.livekit.android"
|
||||
minSdk 26
|
||||
targetSdk 32
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = ['src/main/jniLibs']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//implementation(files('libs/webrtc.jar'))
|
||||
|
||||
implementation 'net.java.dev.jna:jna:5.12.1@aar'
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,24 +0,0 @@
|
||||
package io.livekit.android
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("io.livekit.android", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.livekit.android">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.LKAndroid"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.LKAndroid.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.livekit.android
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.sun.jna.Library
|
||||
import com.sun.jna.Native
|
||||
import org.webrtc.PeerConnectionFactory
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
/*interface LKLib : Library {
|
||||
companion object {
|
||||
internal val Instance: LKLib by lazy {
|
||||
Native.load("livekit_native", LKLib::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
fun test_rust()
|
||||
}*/
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
println("Started activity")
|
||||
|
||||
val opt = PeerConnectionFactory.InitializationOptions.builder(applicationContext).setNativeLibraryName("livekit_native").createInitializationOptions()
|
||||
|
||||
PeerConnectionFactory.initialize(opt)
|
||||
val factory = PeerConnectionFactory.builder().createPeerConnectionFactory()
|
||||
|
||||
//LKLib.Instance.test_rust()
|
||||
|
||||
println("Called Rust fnc")
|
||||
println("Now, start investigating the JNI platform specific stuff !")
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startY="49.59793"
|
||||
android:startX="42.9492"
|
||||
android:endY="92.4963"
|
||||
android:endX="85.84757"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
@@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="108dp"
|
||||
android:width="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:theme="@style/Theme.LKAndroid.AppBarOverlay">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/Theme.LKAndroid.PopupOverlay"
|
||||
android:layout_height="?attr/actionBarSize" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="@dimen/fab_margin"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:srcCompat="@android:drawable/ic_dialog_email" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_host_fragment_content_main"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/nav_graph" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,10 +0,0 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="io.livekit.android.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:title="@string/action_settings"
|
||||
android:orderInCategory="100"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 982 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nav_graph"
|
||||
app:startDestination="@id/FirstFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/FirstFragment"
|
||||
android:name="io.livekit.android.FirstFragment"
|
||||
android:label="@string/first_fragment_label"
|
||||
tools:layout="@layout/fragment_first">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_FirstFragment_to_SecondFragment"
|
||||
app:destination="@id/SecondFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/SecondFragment"
|
||||
android:name="io.livekit.android.SecondFragment"
|
||||
android:label="@string/second_fragment_label"
|
||||
tools:layout="@layout/fragment_second">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_SecondFragment_to_FirstFragment"
|
||||
app:destination="@id/FirstFragment" />
|
||||
</fragment>
|
||||
</navigation>
|
||||
@@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">48dp</dimen>
|
||||
</resources>
|
||||
@@ -1,16 +0,0 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.LKAndroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">200dp</dimen>
|
||||
</resources>
|
||||
@@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">48dp</dimen>
|
||||
</resources>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
@@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
||||
@@ -1,12 +0,0 @@
|
||||
<resources>
|
||||
<string name="app_name">LKAndroid</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<!-- Strings used for fragments for navigation -->
|
||||
<string name="first_fragment_label">First Fragment</string>
|
||||
<string name="second_fragment_label">Second Fragment</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="previous">Previous</string>
|
||||
|
||||
<string name="hello_first_fragment">Hello first fragment</string>
|
||||
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
|
||||
</resources>
|
||||
@@ -1,25 +0,0 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.LKAndroid" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.LKAndroid.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.LKAndroid.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="Theme.LKAndroid.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
@@ -1,11 +0,0 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '7.2.1' apply false
|
||||
id 'com.android.library' version '7.2.1' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app"s APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
@@ -1,6 +0,0 @@
|
||||
#Fri Aug 05 11:43:34 CEST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
@@ -1,185 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
@@ -1,89 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||