diff --git a/Cargo.lock b/Cargo.lock index 485f2a3..5df7241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -473,7 +473,7 @@ dependencies = [ [[package]] name = "gst-meet" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "cocoa", @@ -663,7 +663,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lib-gst-meet" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "async-stream", @@ -751,15 +751,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -[[package]] -name = "matchers" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" -dependencies = [ - "regex-automata", -] - [[package]] name = "matches" version = "0.1.9" @@ -1225,15 +1216,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax", -] - [[package]] name = "regex-syntax" version = "0.6.25" @@ -1651,14 +1633,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab69019741fca4d98be3c62d2b75254528b5432233fd8a4d2739fec20278de48" dependencies = [ "chrono", - "lazy_static", - "matchers", "parking_lot", - "regex", "sharded-slab", "smallvec", "thread_local", - "tracing", "tracing-core", "tracing-log", ] diff --git a/README.md b/README.md index d02d8aa..6df9006 100644 --- a/README.md +++ b/README.md @@ -57,14 +57,14 @@ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ demuxer.audio_0 ! queue ! vorbisdec ! audioconvert ! audioresample ! opusenc name=audio" ``` -Stream the default macOS video & audio inputs to the conference, encoding as VP8 and Opus, display incoming video streams and play back incoming audio (a very basic, but completely native, Jitsi Meet conference!): +Stream the default video & audio inputs to the conference, encoding as VP8 and Opus, composite incoming video streams and play back incoming audio (a very basic, but completely native, Jitsi Meet conference!): ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ - --send-pipeline="avfvideosrc ! queue ! videoconvert ! vp8enc buffer-size=1000 deadline=1 name=video - osxaudiosrc ! queue ! audioconvert ! audioresample ! opusenc name=audio" \ + --send-pipeline="autovideosrc ! queue ! videoconvert ! vp8enc buffer-size=1000 deadline=1 name=video + autoaudiosrc ! queue ! audioconvert ! audioresample ! opusenc name=audio" \ --recv-pipeline-participant-template="opusdec name=audio ! autoaudiosink vp8dec name=video ! videoconvert ! autovideosink" ``` diff --git a/gst-meet/Cargo.toml b/gst-meet/Cargo.toml index a6a593a..db9c859 100644 --- a/gst-meet/Cargo.toml +++ b/gst-meet/Cargo.toml @@ -18,7 +18,6 @@ tokio-stream = { version = "0.1", default-features = false } tracing = { version = "0.1", default-features = false, features = ["attributes", "std"] } tracing-subscriber = { version = "0.2", default-features = false, features = [ "chrono", - "env-filter", "fmt", "smallvec", "parking_lot", diff --git a/gst-meet/src/main.rs b/gst-meet/src/main.rs index f0fcf74..d397fad 100644 --- a/gst-meet/src/main.rs +++ b/gst-meet/src/main.rs @@ -38,6 +38,8 @@ struct Opt { send_pipeline: Option, #[structopt(long)] recv_pipeline_participant_template: Option, + #[structopt(short, long, parse(from_occurrences))] + verbose: u8, } #[cfg(not(target_os = "macos"))] @@ -70,10 +72,14 @@ fn main() { } async fn main_inner() -> Result<()> { - init_tracing(); - let opt = Opt::from_args(); + init_tracing(match opt.verbose { + 0 => tracing::Level::INFO, + 1 => tracing::Level::DEBUG, + _ => tracing::Level::TRACE, + }); + glib::log_set_default_handler(glib::rust_log_handler); let main_loop = glib::MainLoop::new(None, false); gstreamer::init().unwrap(); @@ -189,6 +195,15 @@ async fn main_inner() -> Result<()> { }) }) .await; + + conference + .on_participant_left(move |participant| { + Box::pin(async move { + info!("Participant left: {:?}", participant); + Ok(()) + }) + }) + .await; conference .set_pipeline_state(gstreamer::State::Playing) @@ -215,9 +230,9 @@ async fn main_inner() -> Result<()> { Ok(()) } -fn init_tracing() { +fn init_tracing(level: tracing::Level) { tracing_subscriber::fmt() - .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .with_max_level(level) .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE) .with_target(false) .init(); diff --git a/lib-gst-meet/src/conference.rs b/lib-gst-meet/src/conference.rs index 4cd490e..46772b8 100644 --- a/lib-gst-meet/src/conference.rs +++ b/lib-gst-meet/src/conference.rs @@ -104,6 +104,7 @@ pub(crate) struct JitsiConferenceInner { + Sync, >, >, + on_participant_left: Option Pin> + Send>>) + Send + Sync>>, state: JitsiConferenceState, connected_tx: Option>, connected_rx: Option>, @@ -137,6 +138,7 @@ impl JitsiConference { state: JitsiConferenceState::Discovering, participants: HashMap::new(), on_participant: None, + on_participant_left: None, jingle_session: None, connected_tx: Some(tx), connected_rx: Some(rx), @@ -316,6 +318,17 @@ impl JitsiConference { } } } + + #[tracing::instrument(level = "trace", skip(f))] + pub async fn on_participant_left( + &self, + f: impl (Fn(Participant) -> Pin> + Send>>) + + Send + + Sync + + 'static, + ) { + self.inner.lock().await.on_participant_left = Some(Arc::new(f)); + } } #[async_trait] @@ -560,6 +573,16 @@ impl StanzaFilter for JitsiConference { } } } + else if presence.type_ == presence::Type::Unavailable { + locked_inner.participants.remove(&from.resource.clone()); + debug!("participant left: {:?}", jid); + if let Some(f) = &locked_inner.on_participant_left { + debug!("calling on_participant_left with old participant"); + if let Err(e) = f(participant).await { + warn!("on_participant_left failed: {:?}", e); + } + } + } } } } diff --git a/lib-gst-meet/src/jingle.rs b/lib-gst-meet/src/jingle.rs index 31e1ed4..52f5eb6 100644 --- a/lib-gst-meet/src/jingle.rs +++ b/lib-gst-meet/src/jingle.rs @@ -311,8 +311,8 @@ impl JingleSession { } } - ice_agent.connect_candidate_gathering_done(move |ice_agent, a| { - debug!("ICE candidate-gathering-done {}", a); + ice_agent.connect_candidate_gathering_done(move |_agent, candidates| { + debug!("ICE candidate-gathering-done {:?}", candidates); }); debug!("gathering ICE candidates"); diff --git a/shell.nix b/shell.nix index e42b228..11040dd 100644 --- a/shell.nix +++ b/shell.nix @@ -5,6 +5,12 @@ mkShell { pkg-config glib gst_all_1.gstreamer + gst_all_1.gst-plugins-base + gst_all_1.gst-plugins-good + gst_all_1.gst-plugins-bad libnice - ]; + ] ++ (if stdenv.isDarwin then [ + darwin.apple_sdk.frameworks.AppKit + darwin.apple_sdk.frameworks.Security + ] else []); }