feat: ✨ new protocol client implementation
This commit is contained in:
parent
51c29f7921
commit
5ad6184f13
9 changed files with 497 additions and 267 deletions
360
Cargo.lock
generated
360
Cargo.lock
generated
|
@ -97,7 +97,7 @@ dependencies = [
|
||||||
"jni-sys",
|
"jni-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"ndk 0.9.0",
|
"ndk",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
"ndk-sys 0.6.0+11769913",
|
"ndk-sys 0.6.0+11769913",
|
||||||
"num_enum",
|
"num_enum",
|
||||||
|
@ -406,7 +406,7 @@ version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079"
|
checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.69.5",
|
"bindgen",
|
||||||
"cc",
|
"cc",
|
||||||
"cmake",
|
"cmake",
|
||||||
"dunce",
|
"dunce",
|
||||||
|
@ -457,7 +457,7 @@ dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"cexpr",
|
"cexpr",
|
||||||
"clang-sys",
|
"clang-sys",
|
||||||
"itertools 0.12.1",
|
"itertools",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lazycell",
|
"lazycell",
|
||||||
"log",
|
"log",
|
||||||
|
@ -471,24 +471,6 @@ dependencies = [
|
||||||
"which",
|
"which",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bindgen"
|
|
||||||
version = "0.70.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.9.0",
|
|
||||||
"cexpr",
|
|
||||||
"clang-sys",
|
|
||||||
"itertools 0.13.0",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"rustc-hash 1.1.0",
|
|
||||||
"shlex",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -531,7 +513,7 @@ version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
|
checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -675,6 +657,12 @@ dependencies = [
|
||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "claxon"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "client"
|
name = "client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -684,6 +672,7 @@ dependencies = [
|
||||||
"fixed-resample",
|
"fixed-resample",
|
||||||
"iced",
|
"iced",
|
||||||
"protocol",
|
"protocol",
|
||||||
|
"rodio",
|
||||||
"s2n-quic",
|
"s2n-quic",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
@ -703,9 +692,9 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f"
|
checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -841,22 +830,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coreaudio-rs"
|
name = "coreaudio-rs"
|
||||||
version = "0.11.3"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace"
|
checksum = "1aae284fbaf7d27aa0e292f7677dfbe26503b0d555026f702940805a630eac17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"core-foundation-sys",
|
"libc",
|
||||||
"coreaudio-sys",
|
"objc2-audio-toolbox",
|
||||||
]
|
"objc2-core-audio",
|
||||||
|
"objc2-core-audio-types",
|
||||||
[[package]]
|
"objc2-core-foundation",
|
||||||
name = "coreaudio-sys"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b"
|
|
||||||
dependencies = [
|
|
||||||
"bindgen 0.70.1",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -884,21 +867,24 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpal"
|
name = "cpal"
|
||||||
version = "0.15.3"
|
version = "0.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779"
|
checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alsa",
|
"alsa",
|
||||||
"core-foundation-sys",
|
|
||||||
"coreaudio-rs",
|
"coreaudio-rs",
|
||||||
"dasp_sample",
|
"dasp_sample",
|
||||||
"jni",
|
"jni",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"mach2",
|
"mach2",
|
||||||
"ndk 0.8.0",
|
"ndk",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
"oboe",
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
"objc2-audio-toolbox",
|
||||||
|
"objc2-core-audio",
|
||||||
|
"objc2-core-audio-types",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
@ -969,8 +955,8 @@ checksum = "18e1a09f280e29a8b00bc7e81eca5ac87dca0575639c9422a5fa25a07bb884b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ashpd",
|
"ashpd",
|
||||||
"async-std",
|
"async-std",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
@ -987,6 +973,16 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dispatch2"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"objc2 0.6.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "displaydoc"
|
name = "displaydoc"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
|
@ -1078,6 +1074,15 @@ version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding_rs"
|
||||||
|
version = "0.8.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "endi"
|
name = "endi"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -1644,6 +1649,12 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hound"
|
||||||
|
version = "3.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.63"
|
version = "0.1.63"
|
||||||
|
@ -1978,15 +1989,6 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
|
@ -2077,6 +2079,17 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lewton"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"ogg",
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.172"
|
version = "0.2.172"
|
||||||
|
@ -2280,20 +2293,6 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ndk"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.9.0",
|
|
||||||
"jni-sys",
|
|
||||||
"log",
|
|
||||||
"ndk-sys 0.5.0+25.2.9519653",
|
|
||||||
"num_enum",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -2356,6 +2355,16 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-complex"
|
name = "num-complex"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -2391,6 +2400,7 @@ version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
@ -2461,6 +2471,15 @@ dependencies = [
|
||||||
"objc2-encode",
|
"objc2-encode",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551"
|
||||||
|
dependencies = [
|
||||||
|
"objc2-encode",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-app-kit"
|
name = "objc2-app-kit"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -2470,13 +2489,28 @@ dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"libc",
|
"libc",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-core-data",
|
"objc2-core-data",
|
||||||
"objc2-core-image",
|
"objc2-core-image",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-audio-toolbox"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10cbe18d879e20a4aea544f8befe38bcf52255eb63d3f23eca2842f3319e4c07"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"libc",
|
||||||
|
"objc2 0.6.1",
|
||||||
|
"objc2-core-audio",
|
||||||
|
"objc2-core-audio-types",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-foundation 0.3.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-cloud-kit"
|
name = "objc2-cloud-kit"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -2485,9 +2519,9 @@ checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-core-location",
|
"objc2-core-location",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2497,8 +2531,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
|
checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-core-audio"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca44961e888e19313b808f23497073e3f6b3c22bb485056674c8b49f3b025c82"
|
||||||
|
dependencies = [
|
||||||
|
"dispatch2",
|
||||||
|
"objc2 0.6.1",
|
||||||
|
"objc2-core-audio-types",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-core-audio-types"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0f1cc99bb07ad2ddb6527ddf83db6a15271bb036b3eb94b801cd44fdc666ee1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"objc2 0.6.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2509,8 +2565,19 @@ checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-core-foundation"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"dispatch2",
|
||||||
|
"objc2 0.6.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2520,8 +2587,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
|
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-metal",
|
"objc2-metal",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2532,9 +2599,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
|
checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-contacts",
|
"objc2-contacts",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2553,7 +2620,16 @@ dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"dispatch",
|
"dispatch",
|
||||||
"libc",
|
"libc",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-foundation"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
|
||||||
|
dependencies = [
|
||||||
|
"objc2 0.6.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2563,9 +2639,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
|
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2576,8 +2652,8 @@ checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2588,8 +2664,8 @@ checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-metal",
|
"objc2-metal",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2599,8 +2675,8 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
|
checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2611,12 +2687,12 @@ checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-cloud-kit",
|
"objc2-cloud-kit",
|
||||||
"objc2-core-data",
|
"objc2-core-data",
|
||||||
"objc2-core-image",
|
"objc2-core-image",
|
||||||
"objc2-core-location",
|
"objc2-core-location",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-link-presentation",
|
"objc2-link-presentation",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
"objc2-symbols",
|
"objc2-symbols",
|
||||||
|
@ -2631,8 +2707,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
|
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2643,9 +2719,9 @@ checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
"block2",
|
"block2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-core-location",
|
"objc2-core-location",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2658,26 +2734,12 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oboe"
|
name = "ogg"
|
||||||
version = "0.6.1"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb"
|
checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jni",
|
"byteorder",
|
||||||
"ndk 0.8.0",
|
|
||||||
"ndk-context",
|
|
||||||
"num-derive",
|
|
||||||
"num-traits",
|
|
||||||
"oboe-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "oboe-sys"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2929,6 +2991,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3170,6 +3233,20 @@ dependencies = [
|
||||||
"portable-atomic-util",
|
"portable-atomic-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rodio"
|
||||||
|
version = "0.20.1"
|
||||||
|
source = "git+https://github.com/RustAudio/rodio?rev=071db6df2adfccfe1032be43dd87e5681e34292c#071db6df2adfccfe1032be43dd87e5681e34292c"
|
||||||
|
dependencies = [
|
||||||
|
"claxon",
|
||||||
|
"cpal",
|
||||||
|
"dasp_sample",
|
||||||
|
"hound",
|
||||||
|
"lewton",
|
||||||
|
"num-rational",
|
||||||
|
"symphonia",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roxmltree"
|
name = "roxmltree"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
|
@ -3694,8 +3771,8 @@ dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-quartz-core",
|
"objc2-quartz-core",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"redox_syscall 0.5.12",
|
"redox_syscall 0.5.12",
|
||||||
|
@ -3788,6 +3865,55 @@ dependencies = [
|
||||||
"zeno",
|
"zeno",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"symphonia-bundle-mp3",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-bundle-mp3"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
"symphonia-metadata",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-core"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"bytemuck",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "symphonia-metadata"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_rs",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"symphonia-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.101"
|
version = "2.0.101"
|
||||||
|
@ -5037,10 +5163,10 @@ dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"ndk 0.9.0",
|
"ndk",
|
||||||
"objc2",
|
"objc2 0.5.2",
|
||||||
"objc2-app-kit",
|
"objc2-app-kit",
|
||||||
"objc2-foundation",
|
"objc2-foundation 0.2.2",
|
||||||
"objc2-ui-kit",
|
"objc2-ui-kit",
|
||||||
"orbclient",
|
"orbclient",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
|
|
@ -8,6 +8,7 @@ protocol = { path = "../protocol" }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
s2n-quic = { workspace = true }
|
s2n-quic = { workspace = true }
|
||||||
cpal = "0.15.3"
|
cpal = "0.16.0"
|
||||||
iced = { features = ["tokio"], git = "https://github.com/iced-rs/iced", rev = "d39022432c778a8cda455f40b9c12245db86ce45" }
|
iced = { features = ["tokio"], git = "https://github.com/iced-rs/iced", rev = "d39022432c778a8cda455f40b9c12245db86ce45" }
|
||||||
fixed-resample = "0.8.0"
|
fixed-resample = "0.8.0"
|
||||||
|
rodio = {git = "https://github.com/RustAudio/rodio", rev = "071db6df2adfccfe1032be43dd87e5681e34292c"}
|
||||||
|
|
|
@ -18,13 +18,13 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Signal {
|
struct Controller {
|
||||||
record_control: mpsc::Sender<State>,
|
record_control: mpsc::Sender<State>,
|
||||||
play_control: mpsc::Sender<State>,
|
play_control: mpsc::Sender<State>,
|
||||||
connection_stop_sender: RwLock<Option<oneshot::Sender<bool>>>,
|
connection_stop_sender: RwLock<Option<oneshot::Sender<bool>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signal {
|
impl Controller {
|
||||||
fn reset_connection(&self) -> Result<(), Error> {
|
fn reset_connection(&self) -> Result<(), Error> {
|
||||||
let connection_stop_sender = self.connection_stop_sender.write().unwrap().take();
|
let connection_stop_sender = self.connection_stop_sender.write().unwrap().take();
|
||||||
match connection_stop_sender {
|
match connection_stop_sender {
|
||||||
|
@ -43,7 +43,7 @@ impl Signal {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Channel {
|
struct Channel {
|
||||||
microphone: Arc<broadcast::Sender<f32>>,
|
microphone: Arc<broadcast::Sender<f32>>,
|
||||||
speaker: Arc<broadcast::Sender<f32>>,
|
speaker: Arc<broadcast::Sender<protocol::protocol::Signal>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -90,12 +90,12 @@ pub struct App {
|
||||||
client_config: Arc<ClientConfig>,
|
client_config: Arc<ClientConfig>,
|
||||||
gui_status: Arc<RwLock<GUIStatus>>,
|
gui_status: Arc<RwLock<GUIStatus>>,
|
||||||
channel: Channel,
|
channel: Channel,
|
||||||
signal: Arc<Signal>,
|
controller: Arc<Controller>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn reset_connection(&mut self) -> Result<(), Error> {
|
fn reset_connection(&mut self) -> Result<(), Error> {
|
||||||
self.signal.reset_connection()?;
|
self.controller.reset_connection()?;
|
||||||
self.gui_status.write().unwrap().room = State::Passive;
|
self.gui_status.write().unwrap().room = State::Passive;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ impl App {
|
||||||
microphone: record_sender,
|
microphone: record_sender,
|
||||||
speaker: play_sender,
|
speaker: play_sender,
|
||||||
},
|
},
|
||||||
signal: Signal {
|
controller: Controller {
|
||||||
record_control: record_control.0,
|
record_control: record_control.0,
|
||||||
play_control: play_control.0,
|
play_control: play_control.0,
|
||||||
connection_stop_sender: None.into(),
|
connection_stop_sender: None.into(),
|
||||||
|
@ -168,7 +168,7 @@ impl App {
|
||||||
let speaker_sender = self.channel.speaker.clone();
|
let speaker_sender = self.channel.speaker.clone();
|
||||||
|
|
||||||
let (connection_stop_sender, connection_stop_receiver) = oneshot::channel();
|
let (connection_stop_sender, connection_stop_receiver) = oneshot::channel();
|
||||||
*self.signal.connection_stop_sender.write().unwrap() = Some(connection_stop_sender);
|
*self.controller.connection_stop_sender.write().unwrap() = Some(connection_stop_sender);
|
||||||
|
|
||||||
Task::perform(
|
Task::perform(
|
||||||
async move {
|
async move {
|
||||||
|
@ -211,7 +211,7 @@ impl App {
|
||||||
self.gui_status.write().unwrap().microphone = State::Loading;
|
self.gui_status.write().unwrap().microphone = State::Loading;
|
||||||
|
|
||||||
let gui_status = self.gui_status.clone();
|
let gui_status = self.gui_status.clone();
|
||||||
let signal = self.signal.clone();
|
let signal = self.controller.clone();
|
||||||
Task::perform(
|
Task::perform(
|
||||||
async move { signal.record_control.send(State::Active).await },
|
async move { signal.record_control.send(State::Active).await },
|
||||||
move |result| {
|
move |result| {
|
||||||
|
@ -232,7 +232,7 @@ impl App {
|
||||||
self.gui_status.write().unwrap().microphone = State::Loading;
|
self.gui_status.write().unwrap().microphone = State::Loading;
|
||||||
|
|
||||||
let gui_status = self.gui_status.clone();
|
let gui_status = self.gui_status.clone();
|
||||||
let signal = self.signal.clone();
|
let signal = self.controller.clone();
|
||||||
Task::perform(
|
Task::perform(
|
||||||
async move { signal.record_control.send(State::Passive).await },
|
async move { signal.record_control.send(State::Passive).await },
|
||||||
move |result| {
|
move |result| {
|
||||||
|
@ -253,7 +253,7 @@ impl App {
|
||||||
self.gui_status.write().unwrap().speaker = State::Loading;
|
self.gui_status.write().unwrap().speaker = State::Loading;
|
||||||
|
|
||||||
let gui_status = self.gui_status.clone();
|
let gui_status = self.gui_status.clone();
|
||||||
let signal = self.signal.clone();
|
let signal = self.controller.clone();
|
||||||
Task::perform(
|
Task::perform(
|
||||||
async move { signal.play_control.send(State::Active).await },
|
async move { signal.play_control.send(State::Active).await },
|
||||||
move |result| {
|
move |result| {
|
||||||
|
@ -274,7 +274,7 @@ impl App {
|
||||||
self.gui_status.write().unwrap().speaker = State::Loading;
|
self.gui_status.write().unwrap().speaker = State::Loading;
|
||||||
|
|
||||||
let gui_status = self.gui_status.clone();
|
let gui_status = self.gui_status.clone();
|
||||||
let signal = self.signal.clone();
|
let signal = self.controller.clone();
|
||||||
Task::perform(
|
Task::perform(
|
||||||
async move { signal.play_control.send(State::Passive).await },
|
async move { signal.play_control.send(State::Passive).await },
|
||||||
move |result| {
|
move |result| {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use protocol::protocol::Speaker;
|
||||||
|
use tokio::sync::broadcast;
|
||||||
|
|
||||||
pub mod gui;
|
pub mod gui;
|
||||||
pub mod stream;
|
pub mod stream;
|
||||||
pub mod voice;
|
pub mod voice;
|
||||||
|
@ -5,6 +8,21 @@ pub mod voice;
|
||||||
const MICROPHONE_BUFFER_LENGHT: usize = 1024 * 4;
|
const MICROPHONE_BUFFER_LENGHT: usize = 1024 * 4;
|
||||||
const SPEAKER_BUFFER_LENGHT: usize = 1024 * 16 * 16;
|
const SPEAKER_BUFFER_LENGHT: usize = 1024 * 16 * 16;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SpeakerWithData {
|
||||||
|
speaker: Speaker,
|
||||||
|
audio_sender: broadcast::Sender<f32>,
|
||||||
|
}
|
||||||
|
impl SpeakerWithData {
|
||||||
|
pub fn get_speaker_id(&self) -> u8 {
|
||||||
|
self.speaker.get_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subscribe(&self) -> broadcast::Receiver<f32> {
|
||||||
|
self.audio_sender.subscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ClientConfig {
|
pub struct ClientConfig {
|
||||||
certificate_path: String,
|
certificate_path: String,
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use std::{net::SocketAddr, path::Path, sync::Arc};
|
use std::{net::SocketAddr, path::Path, sync::Arc};
|
||||||
|
|
||||||
use protocol::{Error, NETWORK_BUFFER_LENGTH, Signal, SignalType, SignedAudioDatum};
|
use protocol::{
|
||||||
|
Error,
|
||||||
|
protocol::{NETWORK_DATA_LENGTH, Signal},
|
||||||
|
};
|
||||||
use s2n_quic::{
|
use s2n_quic::{
|
||||||
Client,
|
Client,
|
||||||
client::Connect,
|
client::Connect,
|
||||||
|
@ -22,7 +25,7 @@ pub struct ConnectReturn {
|
||||||
|
|
||||||
pub async fn connect(
|
pub async fn connect(
|
||||||
microphone_receiver: broadcast::Receiver<f32>,
|
microphone_receiver: broadcast::Receiver<f32>,
|
||||||
speaker_sender: Arc<broadcast::Sender<f32>>,
|
speaker_sender: Arc<broadcast::Sender<Signal>>,
|
||||||
client_config: Arc<ClientConfig>,
|
client_config: Arc<ClientConfig>,
|
||||||
) -> Result<ConnectReturn, Error> {
|
) -> Result<ConnectReturn, Error> {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
|
@ -58,10 +61,8 @@ pub async fn connect(
|
||||||
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?;
|
.map_err(|err_val| Error::ConnectionSetup(err_val.to_string()))?;
|
||||||
|
|
||||||
let (receive_stream, send_stream) = stream.split();
|
let (receive_stream, send_stream) = stream.split();
|
||||||
let ready_signal = broadcast::channel(3);
|
|
||||||
|
|
||||||
let send_signals_task = tokio::spawn(send_signals(send_stream, microphone_receiver));
|
let send_signals_task = tokio::spawn(send_signals(send_stream, microphone_receiver));
|
||||||
let speaker_clone = speaker_sender.clone();
|
|
||||||
let receive_signals_task = tokio::spawn(receive_signals(receive_stream, speaker_sender));
|
let receive_signals_task = tokio::spawn(receive_signals(receive_stream, speaker_sender));
|
||||||
|
|
||||||
Ok(ConnectReturn {
|
Ok(ConnectReturn {
|
||||||
|
@ -111,25 +112,15 @@ async fn send_signals(
|
||||||
|
|
||||||
async fn receive_signals(
|
async fn receive_signals(
|
||||||
mut receive_stream: ReceiveStream,
|
mut receive_stream: ReceiveStream,
|
||||||
speaker_sender: Arc<broadcast::Sender<SignedAudioDatum>>,
|
speaker_sender: Arc<broadcast::Sender<Signal>>,
|
||||||
) {
|
) {
|
||||||
let mut network_buffer = [0; NETWORK_BUFFER_LENGTH];
|
let mut network_buffer = [0; NETWORK_DATA_LENGTH];
|
||||||
loop {
|
loop {
|
||||||
match receive_stream.read_exact(&mut network_buffer).await {
|
match receive_stream.read_exact(&mut network_buffer).await {
|
||||||
Ok(_) => match Signal::unpack_signal(&network_buffer) {
|
Ok(_) => match Signal::unpack(network_buffer) {
|
||||||
Ok(received_signal) => match received_signal.signal_type {
|
Ok(signal) => {
|
||||||
SignalType::AudioDatum => match received_signal.unpack_audio() {
|
let _ = speaker_sender.send(signal);
|
||||||
Ok(signed_audio_datum) => {
|
}
|
||||||
let _ = speaker_sender.send(signed_audio_datum);
|
|
||||||
}
|
|
||||||
Err(err_val) => {
|
|
||||||
eprintln!("Error: Unpack Audio | {}", err_val);
|
|
||||||
println!("Warning: Illegal Operation");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SignalType::SpeakerLeft => todo!(),
|
|
||||||
},
|
|
||||||
Err(err_val) => {
|
Err(err_val) => {
|
||||||
eprintln!("Error: Unpack Signal | {}", err_val);
|
eprintln!("Error: Unpack Signal | {}", err_val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,30 @@
|
||||||
use std::sync::Arc;
|
use std::sync::{
|
||||||
|
Arc,
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
use protocol::Error;
|
use protocol::{
|
||||||
|
Error,
|
||||||
|
protocol::{DEFAULT_SAMPLE_RATE, Signal, SignalType},
|
||||||
|
};
|
||||||
|
use rodio::{OutputStream, OutputStreamBuilder, Sink, buffer::SamplesBuffer, mixer::Mixer};
|
||||||
use tokio::sync::{broadcast, mpsc};
|
use tokio::sync::{broadcast, mpsc};
|
||||||
|
|
||||||
use crate::gui::State;
|
use crate::gui::State;
|
||||||
|
|
||||||
|
struct SpeakerSink {
|
||||||
|
speaker_id: u8,
|
||||||
|
sink: Sink,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpeakerSink {
|
||||||
|
fn new(speaker_id: u8, mixer: &Mixer) -> Self {
|
||||||
|
let sink = Sink::connect_new(mixer);
|
||||||
|
Self { speaker_id, sink }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn record(
|
pub async fn record(
|
||||||
mut record_control: mpsc::Receiver<State>,
|
mut record_control: mpsc::Receiver<State>,
|
||||||
record_sender: Arc<broadcast::Sender<f32>>,
|
record_sender: Arc<broadcast::Sender<f32>>,
|
||||||
|
@ -61,66 +80,85 @@ pub async fn record(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn play(
|
async fn signal_handler(
|
||||||
mut play_control: mpsc::Receiver<State>,
|
output_stream: OutputStream,
|
||||||
mut play_receiver: broadcast::Receiver<f32>,
|
mut play_receiver: broadcast::Receiver<Signal>,
|
||||||
) -> Result<(), Error> {
|
play_pause: Arc<AtomicBool>,
|
||||||
let host = cpal::default_host();
|
) {
|
||||||
let output_device = host.default_output_device().unwrap();
|
let mut speaker_list = vec![];
|
||||||
let config = output_device.default_output_config().unwrap().into();
|
|
||||||
println!("Speaker Stream Config = {:#?}", config);
|
|
||||||
|
|
||||||
let output = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
while let Ok(signal) = play_receiver.recv().await {
|
||||||
for sample in data {
|
match signal.get_signal_type() {
|
||||||
match play_receiver.try_recv() {
|
SignalType::AudioDatum => {
|
||||||
Ok(received_sample) => *sample = received_sample,
|
let data = if play_pause.load(std::sync::atomic::Ordering::Relaxed) {
|
||||||
Err(err_val) => match err_val {
|
[signal.get_audio_datum()]
|
||||||
broadcast::error::TryRecvError::Empty => *sample = 0.0,
|
} else {
|
||||||
broadcast::error::TryRecvError::Closed => {
|
[0.0]
|
||||||
eprintln!("Error: Speaker Receive | Local Channel | Channel Closed");
|
};
|
||||||
return;
|
|
||||||
|
let source = SamplesBuffer::new(2, DEFAULT_SAMPLE_RATE, data);
|
||||||
|
|
||||||
|
match speaker_list.binary_search_by(|speaker_sink: &SpeakerSink| {
|
||||||
|
speaker_sink.speaker_id.cmp(&signal.get_speaker_id())
|
||||||
|
}) {
|
||||||
|
Ok(speaker_sink_index) => {
|
||||||
|
let speaker_sink = speaker_list.get(speaker_sink_index).expect("Never");
|
||||||
|
|
||||||
|
speaker_sink.sink.append(source);
|
||||||
}
|
}
|
||||||
broadcast::error::TryRecvError::Lagged(lag_amount) => {
|
Err(_) => {
|
||||||
eprintln!(
|
let speaker_sink =
|
||||||
"Error: Speaker Receive | Local Channel | Lagging by -> {}",
|
SpeakerSink::new(signal.get_speaker_id(), output_stream.mixer());
|
||||||
lag_amount
|
|
||||||
);
|
speaker_sink.sink.append(source);
|
||||||
play_receiver = play_receiver.resubscribe();
|
|
||||||
|
speaker_list.push(speaker_sink);
|
||||||
|
speaker_list.sort_by(|x, y| x.speaker_id.cmp(&y.speaker_id));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
SignalType::SpeakerLeft => {
|
||||||
|
speaker_list
|
||||||
|
.retain(|speaker_sink| speaker_sink.speaker_id != signal.get_speaker_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let output_stream = output_device
|
pub async fn play(
|
||||||
.build_output_stream(&config, output, voice_error, None)
|
mut play_control: mpsc::Receiver<State>,
|
||||||
.unwrap();
|
play_receiver: broadcast::Receiver<Signal>,
|
||||||
|
) {
|
||||||
|
let output_stream = OutputStreamBuilder::open_default_stream().unwrap();
|
||||||
|
let play_pause = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
output_stream
|
let signal_handler = tokio::spawn(signal_handler(
|
||||||
.play()
|
output_stream,
|
||||||
.map_err(|inner| Error::Play(inner.to_string()))?;
|
play_receiver,
|
||||||
|
play_pause.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
tokio::task::block_in_place(|| {
|
tokio::task::block_in_place(|| {
|
||||||
loop {
|
loop {
|
||||||
match play_control.blocking_recv() {
|
match play_control.blocking_recv() {
|
||||||
Some(message) => match message {
|
Some(requested_state) => match requested_state {
|
||||||
State::Active => output_stream
|
State::Active => {
|
||||||
.play()
|
play_pause.store(true, Ordering::Relaxed);
|
||||||
.map_err(|inner| Error::Play(inner.to_string()))?,
|
}
|
||||||
State::Passive => output_stream
|
State::Passive => {
|
||||||
.pause()
|
play_pause.store(false, Ordering::Relaxed);
|
||||||
.map_err(|inner| Error::Play(inner.to_string()))?,
|
}
|
||||||
State::Loading => {}
|
State::Loading => {}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
output_stream
|
signal_handler.abort();
|
||||||
.pause()
|
return;
|
||||||
.map_err(|inner| Error::Play(inner.to_string()))?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
signal_handler.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn voice_error(err_val: cpal::StreamError) {
|
fn voice_error(err_val: cpal::StreamError) {
|
||||||
|
|
|
@ -6,5 +6,6 @@ edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# serde = { workspace = true }
|
# serde = { workspace = true }
|
||||||
# serde_json = { workspace = true }
|
# serde_json = { workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
bincode = { workspace = true }
|
bincode = { workspace = true }
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
|
use tokio::sync::broadcast;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
const SIGNAL_DATA_LENGTH: usize = 4;
|
const SIGNAL_DATA_LENGTH: usize = 4;
|
||||||
const NETWORK_DATA_LENGTH: usize = 6;
|
pub const NETWORK_DATA_LENGTH: usize = 6;
|
||||||
|
pub const SPEAKER_ACTION_CHANNEL_LENGTH: usize = 1024;
|
||||||
|
pub const AUDIO_DATA_SENDER_CHANNEL_LENGTH: usize = 1024 * 16 * 4;
|
||||||
|
pub const DEFAULT_SAMPLE_RATE: u32 = 44100;
|
||||||
|
|
||||||
|
pub type SpeakerWithDataAndAction = (SpeakerWithData, SpeakerAction);
|
||||||
type SignalBufferReturn = [u8; SIGNAL_DATA_LENGTH];
|
type SignalBufferReturn = [u8; SIGNAL_DATA_LENGTH];
|
||||||
type NetworkBufferReturn = [u8; NETWORK_DATA_LENGTH];
|
type NetworkBufferReturn = [u8; NETWORK_DATA_LENGTH];
|
||||||
|
|
||||||
|
@ -26,20 +33,88 @@ impl Speaker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum SpeakerAction {
|
||||||
|
Join,
|
||||||
|
Left,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SpeakerWithData {
|
||||||
|
speaker: Speaker,
|
||||||
|
speaker_action_sender: Arc<broadcast::Sender<(SpeakerWithData, SpeakerAction)>>,
|
||||||
|
audio_data_sender: Arc<broadcast::Sender<f32>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpeakerWithData {
|
||||||
|
pub fn new(speaker: Speaker) -> Self {
|
||||||
|
let speaker_action_sender = broadcast::channel(SPEAKER_ACTION_CHANNEL_LENGTH).0.into();
|
||||||
|
let audio_data_sender = broadcast::channel(AUDIO_DATA_SENDER_CHANNEL_LENGTH)
|
||||||
|
.0
|
||||||
|
.into();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
speaker,
|
||||||
|
speaker_action_sender,
|
||||||
|
audio_data_sender,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_speaker_id(&self) -> u8 {
|
||||||
|
self.speaker.get_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_speaker(&self) -> Speaker {
|
||||||
|
self.speaker
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_speaker_action(&self, speaker_with_data_and_action: SpeakerWithDataAndAction) {
|
||||||
|
let _ = self
|
||||||
|
.speaker_action_sender
|
||||||
|
.send(speaker_with_data_and_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_audio_data_sender(&self) -> Arc<broadcast::Sender<f32>> {
|
||||||
|
self.audio_data_sender.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subscribe_speaker_action_channel(
|
||||||
|
&self,
|
||||||
|
) -> broadcast::Receiver<(SpeakerWithData, SpeakerAction)> {
|
||||||
|
self.speaker_action_sender.subscribe()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subscribe_audio_data_channel(&self) -> broadcast::Receiver<f32> {
|
||||||
|
self.audio_data_sender.subscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Encode, Decode)]
|
||||||
pub enum SignalType {
|
pub enum SignalType {
|
||||||
AudioDatum,
|
AudioDatum,
|
||||||
SpeakerLeft,
|
SpeakerLeft,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Encode, Decode)]
|
#[derive(Debug, Clone, Copy, Encode, Decode)]
|
||||||
pub struct Signal {
|
pub struct Signal {
|
||||||
signal_type: SignalType,
|
signal_type: SignalType,
|
||||||
speaker: Speaker,
|
speaker: Speaker,
|
||||||
data: [u8; SIGNAL_DATA_LENGTH],
|
data: SignalBufferReturn,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Signal {
|
impl Signal {
|
||||||
|
pub fn get_signal_type(&self) -> SignalType {
|
||||||
|
self.signal_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_speaker_id(&self) -> u8 {
|
||||||
|
self.speaker.get_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_audio_datum(&self) -> f32 {
|
||||||
|
f32::from_be_bytes(self.data)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unpack(data: NetworkBufferReturn) -> Result<Self, Error> {
|
pub fn unpack(data: NetworkBufferReturn) -> Result<Self, Error> {
|
||||||
Ok(bincode::decode_from_slice::<Self, _>(&data, BINCODE_CONFIG)
|
Ok(bincode::decode_from_slice::<Self, _>(&data, BINCODE_CONFIG)
|
||||||
.map_err(|inner| Error::Deserialization(inner.to_string()))?
|
.map_err(|inner| Error::Deserialization(inner.to_string()))?
|
||||||
|
|
|
@ -3,7 +3,9 @@ use std::{
|
||||||
sync::{Arc, LazyLock},
|
sync::{Arc, LazyLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
use protocol::protocol::{Signal, Speaker};
|
use protocol::protocol::{
|
||||||
|
Signal, Speaker, SpeakerAction, SpeakerWithData, SpeakerWithDataAndAction,
|
||||||
|
};
|
||||||
use s2n_quic::{
|
use s2n_quic::{
|
||||||
Connection, Server,
|
Connection, Server,
|
||||||
stream::{ReceiveStream, SendStream},
|
stream::{ReceiveStream, SendStream},
|
||||||
|
@ -15,73 +17,45 @@ use tokio::{
|
||||||
|
|
||||||
use crate::ServerConfig;
|
use crate::ServerConfig;
|
||||||
|
|
||||||
const NEW_SPEAKER_LENGTH: usize = u8::MAX as usize;
|
async fn add_speaker(
|
||||||
const AUDIO_BUFFER_LENGTH: usize = 1024 * 16 * 16;
|
speaker_with_data: SpeakerWithData,
|
||||||
|
) -> (
|
||||||
|
broadcast::Receiver<SpeakerWithDataAndAction>,
|
||||||
|
Arc<broadcast::Sender<f32>>,
|
||||||
|
) {
|
||||||
|
// Do this first so receiver can keep track of later insertions, otherwise they just wastes
|
||||||
|
let speaker_action_receiver = speaker_with_data.subscribe_speaker_action_channel();
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
let mut online_speakers = ONLINE_SPEAKERS.write().await;
|
||||||
enum SpeakerAction {
|
for online_speaker in online_speakers.iter() {
|
||||||
Join,
|
speaker_with_data.send_speaker_action((online_speaker.clone(), SpeakerAction::Join));
|
||||||
Left,
|
online_speaker.send_speaker_action((speaker_with_data.clone(), SpeakerAction::Join));
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct SpeakerWithData {
|
|
||||||
speaker: Speaker,
|
|
||||||
speaker_action_sender: broadcast::Sender<(SpeakerWithData, SpeakerAction)>,
|
|
||||||
audio_data_sender: broadcast::Sender<f32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpeakerWithData {
|
|
||||||
async fn new(
|
|
||||||
speaker: Speaker,
|
|
||||||
) -> (
|
|
||||||
broadcast::Receiver<(SpeakerWithData, SpeakerAction)>,
|
|
||||||
broadcast::Sender<f32>,
|
|
||||||
) {
|
|
||||||
let speaker_action_channel = broadcast::channel(NEW_SPEAKER_LENGTH);
|
|
||||||
let audio_data_sender = broadcast::channel(AUDIO_BUFFER_LENGTH).0;
|
|
||||||
|
|
||||||
let speaker_with_data = Self {
|
|
||||||
speaker,
|
|
||||||
speaker_action_sender: speaker_action_channel.0,
|
|
||||||
audio_data_sender: audio_data_sender.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut online_speakers = ONLINE_SPEAKERS.write().await;
|
|
||||||
for online_speaker in online_speakers.iter() {
|
|
||||||
let _ = speaker_with_data
|
|
||||||
.speaker_action_sender
|
|
||||||
.send((online_speaker.clone(), SpeakerAction::Join));
|
|
||||||
let _ = online_speaker
|
|
||||||
.speaker_action_sender
|
|
||||||
.send((speaker_with_data.clone(), SpeakerAction::Join));
|
|
||||||
}
|
|
||||||
|
|
||||||
online_speakers.push(speaker_with_data);
|
|
||||||
online_speakers.sort_by_key(|speaker| speaker.speaker.get_id());
|
|
||||||
|
|
||||||
drop(online_speakers);
|
|
||||||
|
|
||||||
(speaker_action_channel.1, audio_data_sender)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remove(speaker_id: u8) {
|
let audio_data_sender = speaker_with_data.clone_audio_data_sender();
|
||||||
let mut online_speakers = ONLINE_SPEAKERS.write().await;
|
|
||||||
|
|
||||||
let speaker_index =
|
online_speakers.push(speaker_with_data);
|
||||||
online_speakers.binary_search_by_key(&speaker_id, |speaker| speaker.speaker.get_id());
|
online_speakers.sort_by_key(|speaker| speaker.get_speaker_id());
|
||||||
|
|
||||||
match speaker_index {
|
drop(online_speakers);
|
||||||
Ok(speaker_index) => {
|
|
||||||
let speaker = online_speakers.remove(speaker_index);
|
(speaker_action_receiver, audio_data_sender)
|
||||||
for online_speaker in online_speakers.iter() {
|
}
|
||||||
let _ = online_speaker
|
|
||||||
.speaker_action_sender
|
async fn remove_speaker(speaker_id: u8) {
|
||||||
.send((speaker.clone(), SpeakerAction::Left));
|
let mut online_speakers = ONLINE_SPEAKERS.write().await;
|
||||||
}
|
|
||||||
|
let speaker_index =
|
||||||
|
online_speakers.binary_search_by_key(&speaker_id, |speaker| speaker.get_speaker_id());
|
||||||
|
|
||||||
|
match speaker_index {
|
||||||
|
Ok(speaker_index) => {
|
||||||
|
let speaker = online_speakers.remove(speaker_index);
|
||||||
|
for online_speaker in online_speakers.iter() {
|
||||||
|
online_speaker.send_speaker_action((speaker.clone(), SpeakerAction::Left));
|
||||||
}
|
}
|
||||||
Err(_) => return,
|
|
||||||
}
|
}
|
||||||
|
Err(_) => return,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +107,9 @@ async fn handle_client(speaker: Speaker, mut connection: Connection) {
|
||||||
let (receive_stream, send_stream) = stream.split();
|
let (receive_stream, send_stream) = stream.split();
|
||||||
|
|
||||||
let speaker_id = speaker.get_id();
|
let speaker_id = speaker.get_id();
|
||||||
let (speaker_action_receiver, audio_data_sender) = SpeakerWithData::new(speaker).await;
|
|
||||||
|
let speaker_with_data = SpeakerWithData::new(speaker);
|
||||||
|
let (speaker_action_receiver, audio_data_sender) = add_speaker(speaker_with_data).await;
|
||||||
|
|
||||||
tokio::spawn(receive_audio_data(
|
tokio::spawn(receive_audio_data(
|
||||||
receive_stream,
|
receive_stream,
|
||||||
|
@ -158,22 +134,25 @@ async fn send_audio_data(
|
||||||
SpeakerAction::Join => {
|
SpeakerAction::Join => {
|
||||||
let send_stream = send_stream.clone();
|
let send_stream = send_stream.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut audio_data_receiver = speaker_with_data.audio_data_sender.subscribe();
|
let mut audio_data_receiver = speaker_with_data.subscribe_audio_data_channel();
|
||||||
|
|
||||||
while let Ok(audio_datum) = audio_data_receiver.recv().await {
|
while let Ok(audio_datum) = audio_data_receiver.recv().await {
|
||||||
let data = Signal::pack_audio_datum(speaker_with_data.speaker, audio_datum);
|
let data =
|
||||||
|
Signal::pack_audio_datum(speaker_with_data.get_speaker(), audio_datum);
|
||||||
if let Err(err_val) = send_stream.write().await.write_all(&data).await {
|
if let Err(err_val) = send_stream.write().await.write_all(&data).await {
|
||||||
eprintln!("Error: Send Audio Data | Remote | {}", err_val);
|
eprintln!("Error: Send Audio Data | Remote | {}", err_val);
|
||||||
SpeakerWithData::remove(speaker_id).await;
|
remove_speaker(speaker_id).await;
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
SpeakerAction::Left => {
|
SpeakerAction::Left => {
|
||||||
let data = Signal::pack_speaker_left(speaker_with_data.speaker);
|
let data = Signal::pack_speaker_left(speaker_with_data.get_speaker());
|
||||||
if let Err(err_val) = send_stream.write().await.write_all(&data).await {
|
if let Err(err_val) = send_stream.write().await.write_all(&data).await {
|
||||||
eprintln!("Error: Send Speaker Left | Remote | {}", err_val);
|
eprintln!("Error: Send Speaker Left | Remote | {}", err_val);
|
||||||
SpeakerWithData::remove(speaker_id).await;
|
remove_speaker(speaker_id).await;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +162,7 @@ async fn send_audio_data(
|
||||||
async fn receive_audio_data(
|
async fn receive_audio_data(
|
||||||
mut receive_stream: ReceiveStream,
|
mut receive_stream: ReceiveStream,
|
||||||
speaker_id: u8,
|
speaker_id: u8,
|
||||||
audio_data_sender: broadcast::Sender<f32>,
|
audio_data_sender: Arc<broadcast::Sender<f32>>,
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
match receive_stream.read_f32().await {
|
match receive_stream.read_f32().await {
|
||||||
|
@ -192,7 +171,8 @@ async fn receive_audio_data(
|
||||||
}
|
}
|
||||||
Err(err_val) => {
|
Err(err_val) => {
|
||||||
eprintln!("Error: Receive Audio Data | Remote | {}", err_val);
|
eprintln!("Error: Receive Audio Data | Remote | {}", err_val);
|
||||||
SpeakerWithData::remove(speaker_id).await;
|
remove_speaker(speaker_id).await;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue