diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 5d663c4..127ccb8 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -43,7 +43,9 @@ jobs: - name: Install linux dependencies if: ${{ matrix.os == 'ubuntu-latest' }} - run: sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev + run: | + sudo apt update -y + sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev - uses: actions/checkout@v3 with: diff --git a/.github/workflows/ffi-builds.yml b/.github/workflows/ffi-builds.yml index 3cfd7b5..6ef9fe0 100644 --- a/.github/workflows/ffi-builds.yml +++ b/.github/workflows/ffi-builds.yml @@ -51,7 +51,9 @@ jobs: - name: Install linux dependencies if: ${{ matrix.os == 'ubuntu-latest' }} - run: sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev + run: | + sudo apt update -y + sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev - uses: actions/checkout@v3 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d4c5e67..2277185 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -37,7 +37,9 @@ jobs: - name: Install linux dependencies if: ${{ matrix.os == 'ubuntu-latest' }} - run: sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev + run: | + sudo apt update -y + sudo apt install -y libssl-dev libx11-dev libgl1-mesa-dev libxext-dev - uses: actions/checkout@v3 with: diff --git a/Cargo.lock b/Cargo.lock index b369cc3..de9f8ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,12 +41,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.0" @@ -263,6 +257,12 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + [[package]] name = "digest" version = "0.10.6" @@ -735,7 +735,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.0", + "base64", "ring", "serde", "serde_json", @@ -843,8 +843,10 @@ dependencies = [ "env_logger", "futures", "js-sys", + "lazy_static", "livekit-protocol", "log", + "parking_lot", "thiserror", "tokio", "wasm-bindgen", @@ -1234,7 +1236,7 @@ version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ - "base64 0.21.0", + "base64", "bytes", "encoding_rs", "futures-core", @@ -1614,9 +1616,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" dependencies = [ "futures-util", "log", @@ -1686,13 +1688,13 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 6cf6bb0..ca0b9ab 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -181,12 +181,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.0" @@ -203,7 +197,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" name = "basic_room" version = "0.1.0" dependencies = [ + "env_logger", "livekit", + "log", "tokio", ] @@ -604,6 +600,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + [[package]] name = "digest" version = "0.10.6" @@ -727,6 +729,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "epaint" version = "0.21.0" @@ -1209,6 +1224,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.26" @@ -1314,6 +1335,18 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1481,8 +1514,10 @@ dependencies = [ "cxx", "futures", "js-sys", + "lazy_static", "livekit-protocol", "log", + "parking_lot", "thiserror", "tokio", "wasm-bindgen", @@ -2305,7 +2340,7 @@ version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" dependencies = [ - "base64 0.21.0", + "base64", "bytes", "encoding_rs", "futures-core", @@ -2851,9 +2886,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" dependencies = [ "futures-util", "log", @@ -2972,13 +3007,13 @@ checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" [[package]] name = "tungstenite" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", diff --git a/examples/basic_room/Cargo.toml b/examples/basic_room/Cargo.toml index 099a7a1..54f93a6 100644 --- a/examples/basic_room/Cargo.toml +++ b/examples/basic_room/Cargo.toml @@ -5,4 +5,6 @@ edition = "2021" [dependencies] tokio = { version = "1", features = ["full"] } +env_logger = "0.10" livekit = { path = "../../livekit", version = "0.1.1" } +log = "0.4" diff --git a/examples/basic_room/src/main.rs b/examples/basic_room/src/main.rs index 6d9b84d..0c27c0a 100644 --- a/examples/basic_room/src/main.rs +++ b/examples/basic_room/src/main.rs @@ -1,18 +1,21 @@ use livekit::prelude::*; use std::env; -// Basic demo to connect to a room using the specified env variables +// Connect to a room using the specified env variables +// and print all incoming events #[tokio::main] async fn main() { + env_logger::init(); + let url = env::var("LIVEKIT_URL").expect("LIVEKIT_URL is not set"); let token = env::var("LIVEKIT_TOKEN").expect("LIVEKIT_TOKEN is not set"); let (room, mut rx) = Room::connect(&url, &token).await.unwrap(); let session = room.session(); - println!("Connected to room: {} - {}", session.name(), session.sid()); + log::info!("Connected to room: {} - {}", session.name(), session.sid()); while let Some(msg) = rx.recv().await { - println!("Event: {:?}", msg); + log::info!("Event: {:?}", msg); } } diff --git a/livekit-webrtc/Cargo.toml b/livekit-webrtc/Cargo.toml index 28e9aac..acdfe63 100644 --- a/livekit-webrtc/Cargo.toml +++ b/livekit-webrtc/Cargo.toml @@ -14,6 +14,8 @@ thiserror = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] webrtc-sys = { path = "../webrtc-sys", version = "0.1.1" } +lazy_static = "1.4" +parking_lot = { version = "0.12.1", features = ["send_guard"] } futures = { version = "0.3" } tokio = { version = "1", features = ["full"] } cxx = "1.0" diff --git a/livekit-webrtc/src/native/peer_connection_factory.rs b/livekit-webrtc/src/native/peer_connection_factory.rs index a4a2fac..ea435d3 100644 --- a/livekit-webrtc/src/native/peer_connection_factory.rs +++ b/livekit-webrtc/src/native/peer_connection_factory.rs @@ -11,80 +11,76 @@ use crate::video_source::native::NativeVideoSource; use crate::MediaType; use crate::RtcError; use cxx::SharedPtr; -use std::sync::Arc; +use cxx::UniquePtr; +use lazy_static::lazy_static; +use parking_lot::Mutex; +use std::sync::{Arc, Weak}; +use webrtc_sys::logsink as sys_ls; use webrtc_sys::peer_connection as sys_pc; use webrtc_sys::peer_connection_factory as sys_pcf; use webrtc_sys::rtc_error as sys_err; use webrtc_sys::webrtc as sys_webrtc; -impl From for sys_pcf::ffi::ICEServer { - fn from(value: IceServer) -> Self { - sys_pcf::ffi::ICEServer { - urls: value.urls, - username: value.username, - password: value.password, - } - } +lazy_static! { + static ref RTC_RUNTIME: Mutex> = Mutex::new(Weak::new()); } -impl From for sys_pcf::ffi::ContinualGatheringPolicy { - fn from(value: ContinualGatheringPolicy) -> Self { - match value { - ContinualGatheringPolicy::GatherOnce => { - sys_pcf::ffi::ContinualGatheringPolicy::GatherOnce - } - ContinualGatheringPolicy::GatherContinually => { - sys_pcf::ffi::ContinualGatheringPolicy::GatherContinually - } - } - } -} - -impl From for sys_pcf::ffi::IceTransportsType { - fn from(value: IceTransportsType) -> Self { - match value { - IceTransportsType::None => sys_pcf::ffi::IceTransportsType::None, - IceTransportsType::Relay => sys_pcf::ffi::IceTransportsType::Relay, - IceTransportsType::NoHost => sys_pcf::ffi::IceTransportsType::NoHost, - IceTransportsType::All => sys_pcf::ffi::IceTransportsType::All, - } - } -} - -impl From for sys_pcf::ffi::RTCConfiguration { - fn from(value: RtcConfiguration) -> Self { - Self { - ice_servers: value.ice_servers.into_iter().map(Into::into).collect(), - continual_gathering_policy: value.continual_gathering_policy.into(), - ice_transport_type: value.ice_transport_type.into(), - } - } -} - -#[derive(Clone)] -pub struct RTCRuntime { +pub struct RtcRuntime { pub(crate) sys_handle: SharedPtr, + _logsink: UniquePtr, } -impl Default for RTCRuntime { - fn default() -> Self { - Self { - sys_handle: sys_webrtc::ffi::create_rtc_runtime(), +impl RtcRuntime { + pub fn instance() -> Arc { + let mut lk_runtime_ref = RTC_RUNTIME.lock(); + if let Some(lk_runtime) = lk_runtime_ref.upgrade() { + lk_runtime + } else { + log::trace!("RtcRuntime::new()"); + let new_runtime = Arc::new(Self { + sys_handle: sys_webrtc::ffi::create_rtc_runtime(), + _logsink: sys_ls::ffi::new_log_sink(|msg, severity| { + // Forward logs from webrtc to rust log crate + let msg = msg + .strip_suffix("\r\n") + .or(msg.strip_suffix("\n")) + .unwrap_or(&msg); + + let lvl = match severity { + sys_ls::ffi::LoggingSeverity::Verbose => log::Level::Trace, + sys_ls::ffi::LoggingSeverity::Info => log::Level::Debug, // Translte webrtc + // info to debug log level to avoid polluting the user logs + sys_ls::ffi::LoggingSeverity::Warning => log::Level::Warn, + sys_ls::ffi::LoggingSeverity::Error => log::Level::Error, + _ => log::Level::Debug, + }; + + log::log!(target: "libwebrtc", lvl, "{}", msg); + }), + }); + *lk_runtime_ref = Arc::downgrade(&new_runtime); + new_runtime } } } +impl Drop for RtcRuntime { + fn drop(&mut self) { + log::trace!("RtcRuntime::drop()"); + } +} + #[derive(Clone)] pub struct PeerConnectionFactory { sys_handle: SharedPtr, #[allow(unused)] - runtime: RTCRuntime, + runtime: Arc, } impl Default for PeerConnectionFactory { fn default() -> Self { - let runtime = RTCRuntime::default(); + let runtime = RtcRuntime::instance(); Self { sys_handle: sys_pcf::ffi::create_peer_connection_factory(runtime.sys_handle.clone()), runtime, @@ -102,7 +98,7 @@ impl PeerConnectionFactory { unsafe { let observer = Arc::new(imp_pc::PeerObserver::default()); let native_observer = sys_pc::ffi::create_native_peer_connection_observer( - self.runtime.clone().sys_handle, + self.runtime.sys_handle.clone(), Box::new(sys_pc::PeerConnectionObserverWrapper::new(observer.clone())), ); @@ -155,3 +151,48 @@ impl PeerConnectionFactory { .into() } } + +// Conversions +impl From for sys_pcf::ffi::ICEServer { + fn from(value: IceServer) -> Self { + sys_pcf::ffi::ICEServer { + urls: value.urls, + username: value.username, + password: value.password, + } + } +} + +impl From for sys_pcf::ffi::ContinualGatheringPolicy { + fn from(value: ContinualGatheringPolicy) -> Self { + match value { + ContinualGatheringPolicy::GatherOnce => { + sys_pcf::ffi::ContinualGatheringPolicy::GatherOnce + } + ContinualGatheringPolicy::GatherContinually => { + sys_pcf::ffi::ContinualGatheringPolicy::GatherContinually + } + } + } +} + +impl From for sys_pcf::ffi::IceTransportsType { + fn from(value: IceTransportsType) -> Self { + match value { + IceTransportsType::None => sys_pcf::ffi::IceTransportsType::None, + IceTransportsType::Relay => sys_pcf::ffi::IceTransportsType::Relay, + IceTransportsType::NoHost => sys_pcf::ffi::IceTransportsType::NoHost, + IceTransportsType::All => sys_pcf::ffi::IceTransportsType::All, + } + } +} + +impl From for sys_pcf::ffi::RTCConfiguration { + fn from(value: RtcConfiguration) -> Self { + Self { + ice_servers: value.ice_servers.into_iter().map(Into::into).collect(), + continual_gathering_policy: value.continual_gathering_policy.into(), + ice_transport_type: value.ice_transport_type.into(), + } + } +} diff --git a/livekit/Cargo.toml b/livekit/Cargo.toml index d93b9cc..b75d526 100644 --- a/livekit/Cargo.toml +++ b/livekit/Cargo.toml @@ -12,7 +12,7 @@ livekit-protocol = { path = "../livekit-protocol", version = "0.1.0" } prost = "0.11" serde = { version = "1", features = ["derive"] } serde_json = "1.0" -tokio-tungstenite = { version = "0.18", features = ["native-tls"] } +tokio-tungstenite = { version = "0.19", features = ["native-tls"] } tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" parking_lot = { version = "0.12.1", features = ["send_guard"] } diff --git a/livekit/src/room/track/local_audio_track.rs b/livekit/src/room/track/local_audio_track.rs index f1575dc..161f08a 100644 --- a/livekit/src/room/track/local_audio_track.rs +++ b/livekit/src/room/track/local_audio_track.rs @@ -137,7 +137,7 @@ impl LocalAudioTrack { source: NativeAudioSource, ) -> LocalAudioTrack { let rtc_track = LkRuntime::instance() - .pc_factory + .pc_factory() .create_audio_track(&rtc::native::create_random_uuid(), source); Self::new(name.to_string(), rtc_track, options) diff --git a/livekit/src/room/track/local_video_track.rs b/livekit/src/room/track/local_video_track.rs index 23d3a45..53a7e2b 100644 --- a/livekit/src/room/track/local_video_track.rs +++ b/livekit/src/room/track/local_video_track.rs @@ -136,7 +136,7 @@ impl LocalVideoTrack { source: NativeVideoSource, ) -> LocalVideoTrack { let rtc_track = LkRuntime::instance() - .pc_factory + .pc_factory() .create_video_track(&rtc::native::create_random_uuid(), source); Self::new(name.to_string(), rtc_track, options) diff --git a/livekit/src/rtc_engine/lk_runtime.rs b/livekit/src/rtc_engine/lk_runtime.rs index 073b1b7..0868afa 100644 --- a/livekit/src/rtc_engine/lk_runtime.rs +++ b/livekit/src/rtc_engine/lk_runtime.rs @@ -10,7 +10,7 @@ lazy_static! { } pub struct LkRuntime { - pub pc_factory: PeerConnectionFactory, + pc_factory: PeerConnectionFactory, } impl Debug for LkRuntime { @@ -25,19 +25,17 @@ impl LkRuntime { if let Some(lk_runtime) = lk_runtime_ref.upgrade() { lk_runtime } else { - let new_runtime = Arc::new(LkRuntime::default()); + trace!("LkRuntime::new()"); + let new_runtime = Arc::new(Self { + pc_factory: PeerConnectionFactory::default(), + }); *lk_runtime_ref = Arc::downgrade(&new_runtime); new_runtime } } -} -impl Default for LkRuntime { - fn default() -> Self { - trace!("LkRuntime::default()"); - Self { - pc_factory: PeerConnectionFactory::default(), - } + pub fn pc_factory(&self) -> &PeerConnectionFactory { + &self.pc_factory } } diff --git a/livekit/src/rtc_engine/rtc_session.rs b/livekit/src/rtc_engine/rtc_session.rs index 3ebed60..c9de2bc 100644 --- a/livekit/src/rtc_engine/rtc_session.rs +++ b/livekit/src/rtc_engine/rtc_session.rs @@ -176,14 +176,14 @@ impl RtcSession { let mut publisher_pc = PeerTransport::new( lk_runtime - .pc_factory + .pc_factory() .create_peer_connection(rtc_config.clone())?, proto::SignalTarget::Publisher, ); let mut subscriber_pc = PeerTransport::new( lk_runtime - .pc_factory + .pc_factory() .create_peer_connection(rtc_config.clone())?, proto::SignalTarget::Subscriber, ); @@ -666,7 +666,7 @@ impl SessionInner { if track.kind() == TrackKind::Video { let capabilities = LkRuntime::instance() - .pc_factory + .pc_factory() .get_rtp_sender_capabilities(track.kind().into()); let mut matched = Vec::new(); diff --git a/webrtc-sys/build.rs b/webrtc-sys/build.rs index 75bcf7c..a5cbfab 100644 --- a/webrtc-sys/build.rs +++ b/webrtc-sys/build.rs @@ -150,6 +150,7 @@ fn main() { "src/yuv_helper.rs", "src/helper.rs", "src/audio_resampler.rs", + "src/logsink.rs", ]); builder.files(&[ @@ -171,6 +172,7 @@ fn main() { "src/video_decoder_factory.cpp", "src/audio_device.cpp", "src/audio_resampler.cpp", + "src/logsink.cpp", ]); for include in includes { diff --git a/webrtc-sys/include/livekit/logsink.h b/webrtc-sys/include/livekit/logsink.h new file mode 100644 index 0000000..b6449ee --- /dev/null +++ b/webrtc-sys/include/livekit/logsink.h @@ -0,0 +1,46 @@ +/* + * Copyright 2023 LiveKit + * + * 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 + * + * http://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. + */ + +#pragma once + +#include "livekit/webrtc.h" +#include "rtc_base/logging.h" +#include "rust/cxx.h" + +namespace livekit { +class LogSink; +} // namespace livekit +#include "webrtc-sys/src/logsink.rs.h" + + +namespace livekit { + +class LogSink : public rtc::LogSink { +public: + LogSink(rust::Fn fnc); + ~LogSink(); + + void OnLogMessage(const std::string& message, rtc::LoggingSeverity severity) override; + void OnLogMessage(const std::string& message) override {} + +private: + rust::Fn fnc_; +}; + +std::unique_ptr new_log_sink(rust::Fn fnc); + +} // namespace livekit + diff --git a/webrtc-sys/src/lib.rs b/webrtc-sys/src/lib.rs index 0efc7eb..bc9607a 100644 --- a/webrtc-sys/src/lib.rs +++ b/webrtc-sys/src/lib.rs @@ -3,6 +3,7 @@ pub mod candidate; pub mod data_channel; pub mod helper; pub mod jsep; +pub mod logsink; pub mod media_stream; pub mod peer_connection; pub mod peer_connection_factory; diff --git a/webrtc-sys/src/logsink.cpp b/webrtc-sys/src/logsink.cpp new file mode 100644 index 0000000..c543edf --- /dev/null +++ b/webrtc-sys/src/logsink.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2023 LiveKit + * + * 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 + * + * http://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. + */ + +#include + +#include "livekit/logsink.h" + +namespace livekit { + +LogSink::LogSink(rust::Fn fnc) : fnc_(fnc) { + rtc::LogMessage::AddLogToStream(this, rtc::LoggingSeverity::LS_VERBOSE); +} + +LogSink::~LogSink() { + rtc::LogMessage::RemoveLogToStream(this); +} + +void LogSink::OnLogMessage(const std::string& message, rtc::LoggingSeverity severity) { + fnc_(rust::String(message), static_cast(severity)); +} + +std::unique_ptr new_log_sink(rust::Fn fnc) { + return std::make_unique(fnc); +} + +} + diff --git a/webrtc-sys/src/logsink.rs b/webrtc-sys/src/logsink.rs new file mode 100644 index 0000000..6d63f97 --- /dev/null +++ b/webrtc-sys/src/logsink.rs @@ -0,0 +1,24 @@ +use crate::impl_thread_safety; + +#[cxx::bridge(namespace = "livekit")] +pub mod ffi { + + #[derive(Debug)] + #[repr(i32)] + pub enum LoggingSeverity { + Verbose, + Info, + Warning, + Error, + None, + } + + unsafe extern "C++" { + include!("livekit/logsink.h"); + + type LogSink; + fn new_log_sink(fnc: fn(String, LoggingSeverity)) -> UniquePtr; + } +} + +impl_thread_safety!(ffi::LogSink, Send + Sync);