Switch fully to Rust Livekit (redux) (#27126)

Swift bindings BEGONE

Release Notes:

- Switched from using the Swift LiveKit bindings, to the Rust bindings,
fixing https://github.com/zed-industries/zed/issues/9396, a crash when
leaving a collaboration session, and making Zed easier to build.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Michael Sloan <michael@zed.dev>
This commit is contained in:
Mikayla Maki
2025-03-28 17:58:23 +00:00
committed by GitHub
co-authored by Conrad Irwin Michael Sloan
parent c8fb95cd1b
commit 8a307e7b89
68 changed files with 2393 additions and 7579 deletions
@@ -0,0 +1,125 @@
use crate::{
test::{Room, WeakRoom},
AudioStream, LocalAudioTrack, LocalTrackPublication, LocalVideoTrack, Participant,
ParticipantIdentity, RemoteTrack, RemoteTrackPublication, TrackSid,
};
use anyhow::Result;
use collections::HashMap;
use gpui::{AsyncApp, ScreenCaptureSource, ScreenCaptureStream};
#[derive(Clone, Debug)]
pub struct LocalParticipant {
pub(crate) identity: ParticipantIdentity,
pub(crate) room: Room,
}
#[derive(Clone, Debug)]
pub struct RemoteParticipant {
pub(crate) identity: ParticipantIdentity,
pub(crate) room: WeakRoom,
}
impl Participant {
pub fn identity(&self) -> ParticipantIdentity {
match self {
Participant::Local(participant) => participant.identity.clone(),
Participant::Remote(participant) => participant.identity.clone(),
}
}
}
impl LocalParticipant {
pub async fn unpublish_track(&self, track: TrackSid, _cx: &AsyncApp) -> Result<()> {
self.room
.test_server()
.unpublish_track(self.room.token(), &track)
.await
}
pub(crate) async fn publish_microphone_track(
&self,
_cx: &AsyncApp,
) -> Result<(LocalTrackPublication, AudioStream)> {
let this = self.clone();
let server = this.room.test_server();
let sid = server
.publish_audio_track(this.room.token(), &LocalAudioTrack {})
.await?;
Ok((
LocalTrackPublication {
room: self.room.downgrade(),
sid,
},
AudioStream {},
))
}
pub async fn publish_screenshare_track(
&self,
_source: &dyn ScreenCaptureSource,
_cx: &mut AsyncApp,
) -> Result<(LocalTrackPublication, Box<dyn ScreenCaptureStream>)> {
let this = self.clone();
let server = this.room.test_server();
let sid = server
.publish_video_track(this.room.token(), LocalVideoTrack {})
.await?;
Ok((
LocalTrackPublication {
room: self.room.downgrade(),
sid,
},
Box::new(TestScreenCaptureStream {}),
))
}
}
impl RemoteParticipant {
pub fn track_publications(&self) -> HashMap<TrackSid, RemoteTrackPublication> {
if let Some(room) = self.room.upgrade() {
let server = room.test_server();
let audio = server
.audio_tracks(room.token())
.unwrap()
.into_iter()
.filter(|track| track.publisher_id() == self.identity)
.map(|track| {
(
track.sid(),
RemoteTrackPublication {
sid: track.sid(),
room: self.room.clone(),
track: RemoteTrack::Audio(track),
},
)
});
let video = server
.video_tracks(room.token())
.unwrap()
.into_iter()
.filter(|track| track.publisher_id() == self.identity)
.map(|track| {
(
track.sid(),
RemoteTrackPublication {
sid: track.sid(),
room: self.room.clone(),
track: RemoteTrack::Video(track),
},
)
});
audio.chain(video).collect()
} else {
HashMap::default()
}
}
pub fn identity(&self) -> ParticipantIdentity {
self.identity.clone()
}
}
struct TestScreenCaptureStream;
impl gpui::ScreenCaptureStream for TestScreenCaptureStream {}
@@ -0,0 +1,100 @@
use gpui::App;
use crate::{test::WeakRoom, RemoteTrack, TrackSid};
#[derive(Clone, Debug)]
pub struct LocalTrackPublication {
pub(crate) sid: TrackSid,
pub(crate) room: WeakRoom,
}
#[derive(Clone, Debug)]
pub struct RemoteTrackPublication {
pub(crate) sid: TrackSid,
pub(crate) room: WeakRoom,
pub(crate) track: RemoteTrack,
}
impl LocalTrackPublication {
pub fn sid(&self) -> TrackSid {
self.sid.clone()
}
pub fn mute(&self, _cx: &App) {
self.set_mute(true)
}
pub fn unmute(&self, _cx: &App) {
self.set_mute(false)
}
fn set_mute(&self, mute: bool) {
if let Some(room) = self.room.upgrade() {
room.test_server()
.set_track_muted(&room.token(), &self.sid, mute)
.ok();
}
}
pub fn is_muted(&self) -> bool {
if let Some(room) = self.room.upgrade() {
room.test_server()
.is_track_muted(&room.token(), &self.sid)
.unwrap_or(false)
} else {
false
}
}
}
impl RemoteTrackPublication {
pub fn sid(&self) -> TrackSid {
self.sid.clone()
}
pub fn track(&self) -> Option<RemoteTrack> {
Some(self.track.clone())
}
pub fn is_audio(&self) -> bool {
matches!(self.track, RemoteTrack::Audio(_))
}
pub fn is_muted(&self) -> bool {
if let Some(room) = self.room.upgrade() {
room.test_server()
.is_track_muted(&room.token(), &self.sid)
.unwrap_or(false)
} else {
false
}
}
pub fn is_enabled(&self) -> bool {
if let Some(room) = self.room.upgrade() {
!room.0.lock().paused_audio_tracks.contains(&self.sid)
} else {
false
}
}
pub fn set_enabled(&self, enabled: bool, _cx: &App) {
if let Some(room) = self.room.upgrade() {
let paused_audio_tracks = &mut room.0.lock().paused_audio_tracks;
if enabled {
paused_audio_tracks.remove(&self.sid);
} else {
paused_audio_tracks.insert(self.sid.clone());
}
}
}
}
impl RemoteTrack {
pub fn set_enabled(&self, enabled: bool, _cx: &App) {
match self {
RemoteTrack::Audio(remote_audio_track) => remote_audio_track.set_enabled(enabled),
RemoteTrack::Video(remote_video_track) => remote_video_track.set_enabled(enabled),
}
}
}
@@ -0,0 +1,75 @@
use std::sync::Arc;
use crate::{
test::{TestServerAudioTrack, TestServerVideoTrack, WeakRoom},
ParticipantIdentity, TrackSid,
};
#[derive(Clone, Debug)]
pub struct LocalVideoTrack {}
#[derive(Clone, Debug)]
pub struct LocalAudioTrack {}
#[derive(Clone, Debug)]
pub struct RemoteVideoTrack {
pub(crate) server_track: Arc<TestServerVideoTrack>,
pub(crate) _room: WeakRoom,
}
#[derive(Clone, Debug)]
pub struct RemoteAudioTrack {
pub(crate) server_track: Arc<TestServerAudioTrack>,
pub(crate) room: WeakRoom,
}
impl RemoteAudioTrack {
pub fn sid(&self) -> TrackSid {
self.server_track.sid.clone()
}
pub fn publisher_id(&self) -> ParticipantIdentity {
self.server_track.publisher_id.clone()
}
pub fn enabled(&self) -> bool {
if let Some(room) = self.room.upgrade() {
!room
.0
.lock()
.paused_audio_tracks
.contains(&self.server_track.sid)
} else {
false
}
}
pub fn set_enabled(&self, enabled: bool) {
let Some(room) = self.room.upgrade() else {
return;
};
if enabled {
room.0
.lock()
.paused_audio_tracks
.remove(&self.server_track.sid);
} else {
room.0
.lock()
.paused_audio_tracks
.insert(self.server_track.sid.clone());
}
}
}
impl RemoteVideoTrack {
pub fn sid(&self) -> TrackSid {
self.server_track.sid.clone()
}
pub fn publisher_id(&self) -> ParticipantIdentity {
self.server_track.publisher_id.clone()
}
pub(crate) fn set_enabled(&self, _enabled: bool) {}
}