diff --git a/.vscode/launch.json b/.vscode/launch.json index 2e0006786..16af97373 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,6 +7,18 @@ "name": "wgpu_room(debug)", "program": "${workspaceFolder}/examples/target/debug/wgpu_room", "preLaunchTask": "build" + }, + { + "type": "lldb", + "request": "launch", + "name": "local_audio(debug)", + "program": "${workspaceFolder}/target/debug/local_audio", + "preLaunchTask": "build", + "env": { + "LIVEKIT_URL": "ws://localhost:7880", + "LIVEKIT_API_KEY": "testkey", + "LIVEKIT_API_SECRET": "testsecret", + }, } ] } \ No newline at end of file diff --git a/examples/local_audio/src/main.rs b/examples/local_audio/src/main.rs index 26cf14ab5..82b832991 100644 --- a/examples/local_audio/src/main.rs +++ b/examples/local_audio/src/main.rs @@ -339,6 +339,38 @@ async fn stream_audio_to_livekit_with_shared_apm( Ok(()) } +async fn handle_room_events(room: Arc) -> Result<()> { + let mut room_events = room.subscribe(); + + while let Some(event) = room_events.recv().await { + match event { + RoomEvent::TrackMuted { participant, publication } => { + println!( + "Track muted by {}: {} ({:?})", + participant.identity(), + publication.name(), + publication.kind() + ); + } + + RoomEvent::TrackUnmuted { participant, publication } => { + println!( + "Track unmuted by {}: {} ({:?})", + participant.identity(), + publication.name(), + publication.kind() + ); + } + _ => { + // Handle other room events as needed + debug!("Room event: {:?}", event); + } + } + } + + Ok(()) +} + async fn handle_remote_audio_streams( room: Arc, mixer: AudioMixer, @@ -573,6 +605,9 @@ async fn main() -> Result<()> { 1000, // 1 second buffer ); + // Handle room events + tokio::spawn(handle_room_events(room.clone())); + // Create and publish audio track let track = LocalAudioTrack::create_audio_track( "microphone", @@ -581,7 +616,7 @@ async fn main() -> Result<()> { room.local_participant() .publish_track( - LocalTrack::Audio(track), + LocalTrack::Audio(track.clone()), TrackPublishOptions { source: TrackSource::Microphone, ..Default::default() }, ) .await?; @@ -702,6 +737,17 @@ async fn main() -> Result<()> { if _audio_playback.is_some() { "Enabled" } else { "Disabled" } ); + // Demonstrate muting/unmuting the microphone track + tokio::spawn(async move { + // Demonstrate muting/unmuting after some time + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + track.mute(); + info!("Microphone muted for 5 seconds..."); + tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; + track.unmute(); + info!("Microphone unmuted."); + }); + // Wait for Ctrl+C tokio::signal::ctrl_c().await?; info!("\nShutting down..."); diff --git a/livekit/src/room/participant/local_participant.rs b/livekit/src/room/participant/local_participant.rs index a9a2320fd..105f53efa 100644 --- a/livekit/src/room/participant/local_participant.rs +++ b/livekit/src/room/participant/local_participant.rs @@ -278,6 +278,9 @@ impl LocalParticipant { let publication = LocalTrackPublication::new(track_info.clone(), track.clone()); track.update_info(track_info); // Update sid + source + // set track for publication to listen mute/unmute events + publication.set_track(Some(track.clone().into())); + let transceiver = self.inner.rtc_engine.create_sender(track.clone(), options.clone(), encodings).await?; diff --git a/livekit/src/room/participant/remote_participant.rs b/livekit/src/room/participant/remote_participant.rs index a4e1df2ae..0c752afd4 100644 --- a/livekit/src/room/participant/remote_participant.rs +++ b/livekit/src/room/participant/remote_participant.rs @@ -149,6 +149,7 @@ impl RemoteParticipant { name: remote_publication.name(), r#type: proto::TrackType::from(remote_publication.kind()) as i32, source: proto::TrackSource::from(remote_publication.source()) as i32, + muted: remote_publication.is_muted(), ..Default::default() }); diff --git a/livekit/src/room/track/mod.rs b/livekit/src/room/track/mod.rs index 79d0ab122..230234360 100644 --- a/livekit/src/room/track/mod.rs +++ b/livekit/src/room/track/mod.rs @@ -204,7 +204,7 @@ pub(super) fn set_muted(inner: &Arc, track: &Track, muted: bool) { if let Some(on_mute) = inner.events.lock().muted.as_ref() { on_mute(track.clone()); } - } else if let Some(on_unmute) = inner.events.lock().muted.as_ref() { + } else if let Some(on_unmute) = inner.events.lock().unmuted.as_ref() { on_unmute(track.clone()); } }