Fix race condition in sharing mic on connection

Mikayla Maki and antonio created

co-authored-by: antonio <antonio@zed.dev>

Change summary

crates/call/src/room.rs                                                        | 32 
crates/collab_ui/src/collab_ui.rs                                              |  8 
crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift |  9 
3 files changed, 17 insertions(+), 32 deletions(-)

Detailed changes

crates/call/src/room.rs 🔗

@@ -148,8 +148,13 @@ impl Room {
                 }
             });
 
-            cx.foreground()
-                .spawn(room.connect(&connection_info.server_url, &connection_info.token))
+            let connect = room.connect(&connection_info.server_url, &connection_info.token);
+            cx.spawn(|this, mut cx| async move {
+                    connect.await?;
+                    this.update(&mut cx, |this, cx| this.share_microphone(cx)).await?;
+
+                    anyhow::Ok(())
+                })
                 .detach_and_log_err(cx);
 
             Some(LiveKitRoom {
@@ -228,15 +233,6 @@ impl Room {
                 .await
             {
                 Ok(()) => {
-                    if option_env!("START_MIC").is_some()
-                        || &*util::channel::RELEASE_CHANNEL != &ReleaseChannel::Dev
-                    {
-                        let share_mic = room.update(&mut cx, |room, cx| room.share_mic(cx));
-                        cx.update(|cx| {
-                            cx.background().spawn(share_mic).detach_and_log_err(cx);
-                        });
-                    }
-
                     Ok(room)
                 }
                 Err(error) => Err(anyhow!("room creation failed: {:?}", error)),
@@ -266,14 +262,6 @@ impl Room {
             room.update(&mut cx, |room, cx| {
                 room.leave_when_empty = true;
                 room.apply_room_update(room_proto, cx)?;
-
-                if option_env!("START_MIC").is_some()
-                    || &*util::channel::RELEASE_CHANNEL != &ReleaseChannel::Dev
-                {
-                    let share_mic = room.share_mic(cx);
-                    cx.background().spawn(share_mic).detach_and_log_err(cx);
-                }
-
                 anyhow::Ok(())
             })?;
             Ok(room)
@@ -1022,7 +1010,7 @@ impl Room {
         self.live_kit.as_ref().map(|live_kit| live_kit.deafened)
     }
 
-    pub fn share_mic(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
+    pub fn share_microphone(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
         if self.status.is_offline() {
             return Task::ready(Err(anyhow!("room is offline")));
         } else if self.is_sharing_mic() {
@@ -1225,11 +1213,11 @@ impl Room {
                     .room
                     .remote_audio_track_publications(&participant.user.id.to_string())
                 {
-                    tasks.push(cx.background().spawn(track.set_enabled(!live_kit.deafened)));
+                    tasks.push(cx.foreground().spawn(track.set_enabled(!live_kit.deafened)));
                 }
             }
 
-            Ok(cx.background().spawn(async move {
+            Ok(cx.foreground().spawn(async move {
                 for task in tasks {
                     task.await?;
                 }

crates/collab_ui/src/collab_ui.rs 🔗

@@ -16,7 +16,7 @@ use std::sync::Arc;
 use util::ResultExt;
 use workspace::AppState;
 
-actions!(collab, [ToggleScreenSharing, ToggleMute, ToggleDeafen, ShareMic]);
+actions!(collab, [ToggleScreenSharing, ToggleMute, ToggleDeafen, ShareMicrophone]);
 
 pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
     collab_titlebar_item::init(cx);
@@ -30,7 +30,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
     cx.add_global_action(toggle_screen_sharing);
     cx.add_global_action(toggle_mute);
     cx.add_global_action(toggle_deafen);
-    cx.add_global_action(share_mic);
+    cx.add_global_action(share_microphone);
 }
 
 pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut AppContext) {
@@ -62,8 +62,8 @@ pub fn toggle_deafen(_: &ToggleDeafen, cx: &mut AppContext) {
     }
 }
 
-pub fn share_mic(_: &ShareMic, cx: &mut AppContext) {
+pub fn share_microphone(_: &ShareMicrophone, cx: &mut AppContext) {
     if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
-        room.update(cx, Room::share_mic).detach_and_log_err(cx)
+        room.update(cx, Room::share_microphone).detach_and_log_err(cx)
     }
 }

crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift 🔗

@@ -10,7 +10,7 @@ class LKRoomDelegate: RoomDelegate {
     var onDidUnsubscribeFromRemoteAudioTrack: @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void
     var onDidSubscribeToRemoteVideoTrack: @convention(c) (UnsafeRawPointer, CFString, CFString, UnsafeRawPointer) -> Void
     var onDidUnsubscribeFromRemoteVideoTrack: @convention(c) (UnsafeRawPointer, CFString, CFString) -> Void
-    
+
     init(
         data: UnsafeRawPointer,
         onDidDisconnect: @escaping @convention(c) (UnsafeRawPointer) -> Void,
@@ -40,7 +40,7 @@ class LKRoomDelegate: RoomDelegate {
             self.onDidSubscribeToRemoteAudioTrack(self.data, participant.identity as CFString, track.sid! as CFString, Unmanaged.passUnretained(track).toOpaque())
         }
     }
-    
+
     func room(_ room: Room, participant: RemoteParticipant, didUnsubscribe publication: RemoteTrackPublication, track: Track) {
         if track.kind == .video {
             self.onDidUnsubscribeFromRemoteVideoTrack(self.data, participant.identity as CFString, track.sid! as CFString)
@@ -279,13 +279,10 @@ public func LKRemoteTrackPublicationSetEnabled(
     callback_data: UnsafeRawPointer
 ) {
     let publication = Unmanaged<RemoteTrackPublication>.fromOpaque(publication).takeUnretainedValue()
-    
+
     publication.set(enabled: enabled).then {
         on_complete(callback_data, nil)
     }.catch { error in
         on_complete(callback_data, error.localizedDescription as CFString)
     }
 }
-
-
-