Handle reconnects to the livekit server in which local tracks are unpublished (#3992)

Release notes:

* Fixed a bug where network interruptions could cause audio and screen
sharing to stop working without indicating that they were stopped, and
there was no way to restart the audio stream.
This commit is contained in:
Max Brunsfeld 2024-01-10 16:34:11 -08:00 committed by GitHub
commit cb5d4edc4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 314 additions and 202 deletions

View file

@ -15,10 +15,7 @@ use gpui::{
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakModel,
};
use language::LanguageRegistry;
use live_kit_client::{
LocalAudioTrack, LocalTrackPublication, LocalVideoTrack, RemoteAudioTrackUpdate,
RemoteVideoTrackUpdate,
};
use live_kit_client::{LocalAudioTrack, LocalTrackPublication, LocalVideoTrack, RoomUpdate};
use postage::{sink::Sink, stream::Stream, watch};
use project::Project;
use settings::Settings as _;
@ -131,11 +128,11 @@ impl Room {
}
});
let _maintain_video_tracks = cx.spawn({
let _handle_updates = cx.spawn({
let room = room.clone();
move |this, mut cx| async move {
let mut track_video_changes = room.remote_video_track_updates();
while let Some(track_change) = track_video_changes.next().await {
let mut updates = room.updates();
while let Some(update) = updates.next().await {
let this = if let Some(this) = this.upgrade() {
this
} else {
@ -143,26 +140,7 @@ impl Room {
};
this.update(&mut cx, |this, cx| {
this.remote_video_track_updated(track_change, cx).log_err()
})
.ok();
}
}
});
let _maintain_audio_tracks = cx.spawn({
let room = room.clone();
|this, mut cx| async move {
let mut track_audio_changes = room.remote_audio_track_updates();
while let Some(track_change) = track_audio_changes.next().await {
let this = if let Some(this) = this.upgrade() {
this
} else {
break;
};
this.update(&mut cx, |this, cx| {
this.remote_audio_track_updated(track_change, cx).log_err()
this.live_kit_room_updated(update, cx).log_err()
})
.ok();
}
@ -195,7 +173,7 @@ impl Room {
deafened: false,
speaking: false,
_maintain_room,
_maintain_tracks: [_maintain_video_tracks, _maintain_audio_tracks],
_handle_updates,
})
} else {
None
@ -877,8 +855,8 @@ impl Room {
.remote_audio_track_publications(&user.id.to_string());
for track in video_tracks {
this.remote_video_track_updated(
RemoteVideoTrackUpdate::Subscribed(track),
this.live_kit_room_updated(
RoomUpdate::SubscribedToRemoteVideoTrack(track),
cx,
)
.log_err();
@ -887,8 +865,8 @@ impl Room {
for (track, publication) in
audio_tracks.iter().zip(publications.iter())
{
this.remote_audio_track_updated(
RemoteAudioTrackUpdate::Subscribed(
this.live_kit_room_updated(
RoomUpdate::SubscribedToRemoteAudioTrack(
track.clone(),
publication.clone(),
),
@ -979,13 +957,13 @@ impl Room {
}
}
fn remote_video_track_updated(
fn live_kit_room_updated(
&mut self,
change: RemoteVideoTrackUpdate,
update: RoomUpdate,
cx: &mut ModelContext<Self>,
) -> Result<()> {
match change {
RemoteVideoTrackUpdate::Subscribed(track) => {
match update {
RoomUpdate::SubscribedToRemoteVideoTrack(track) => {
let user_id = track.publisher_id().parse()?;
let track_id = track.sid().to_string();
let participant = self
@ -997,7 +975,8 @@ impl Room {
participant_id: participant.peer_id,
});
}
RemoteVideoTrackUpdate::Unsubscribed {
RoomUpdate::UnsubscribedFromRemoteVideoTrack {
publisher_id,
track_id,
} => {
@ -1011,19 +990,8 @@ impl Room {
participant_id: participant.peer_id,
});
}
}
cx.notify();
Ok(())
}
fn remote_audio_track_updated(
&mut self,
change: RemoteAudioTrackUpdate,
cx: &mut ModelContext<Self>,
) -> Result<()> {
match change {
RemoteAudioTrackUpdate::ActiveSpeakersChanged { speakers } => {
RoomUpdate::ActiveSpeakersChanged { speakers } => {
let mut speaker_ids = speakers
.into_iter()
.filter_map(|speaker_sid| speaker_sid.parse().ok())
@ -1045,9 +1013,9 @@ impl Room {
}
}
}
cx.notify();
}
RemoteAudioTrackUpdate::MuteChanged { track_id, muted } => {
RoomUpdate::RemoteAudioTrackMuteChanged { track_id, muted } => {
let mut found = false;
for participant in &mut self.remote_participants.values_mut() {
for track in participant.audio_tracks.values() {
@ -1061,10 +1029,9 @@ impl Room {
break;
}
}
cx.notify();
}
RemoteAudioTrackUpdate::Subscribed(track, publication) => {
RoomUpdate::SubscribedToRemoteAudioTrack(track, publication) => {
let user_id = track.publisher_id().parse()?;
let track_id = track.sid().to_string();
let participant = self
@ -1078,7 +1045,8 @@ impl Room {
participant_id: participant.peer_id,
});
}
RemoteAudioTrackUpdate::Unsubscribed {
RoomUpdate::UnsubscribedFromRemoteAudioTrack {
publisher_id,
track_id,
} => {
@ -1092,6 +1060,28 @@ impl Room {
participant_id: participant.peer_id,
});
}
RoomUpdate::LocalAudioTrackUnpublished { publication } => {
log::info!("unpublished audio track {}", publication.sid());
if let Some(room) = &mut self.live_kit {
room.microphone_track = LocalTrack::None;
}
}
RoomUpdate::LocalVideoTrackUnpublished { publication } => {
log::info!("unpublished video track {}", publication.sid());
if let Some(room) = &mut self.live_kit {
room.screen_track = LocalTrack::None;
}
}
RoomUpdate::LocalAudioTrackPublished { publication } => {
log::info!("published audio track {}", publication.sid());
}
RoomUpdate::LocalVideoTrackPublished { publication } => {
log::info!("published video track {}", publication.sid());
}
}
cx.notify();
@ -1597,7 +1587,7 @@ struct LiveKitRoom {
speaking: bool,
next_publish_id: usize,
_maintain_room: Task<()>,
_maintain_tracks: [Task<()>; 2],
_handle_updates: Task<()>,
}
impl LiveKitRoom {