Revert "Use livekit's Rust SDK instead of their swift SDK (#13343)" (#20809)

Issues found:

* audio does not work well with various set-ups using USB
* switching audio during initial join may leave the client with no audio
at all
* audio streaming is done on the main thread, beachballing certain
set-ups
* worse screenshare quality (seems that there's no dynamic scaling
anymore, compared to the Swift SDK)

This reverts commit 1235d0808e.

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov
2024-11-18 11:43:53 +02:00
committed by GitHub
parent 59a355da74
commit d92166f9f6
48 changed files with 3599 additions and 4288 deletions
-6
View File
@@ -13,12 +13,6 @@ rustflags = ["-C", "link-arg=-fuse-ld=mold"]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[target.aarch64-apple-darwin]
rustflags = ["-C", "link-args=-Objc -all_load"]
[target.x86_64-apple-darwin]
rustflags = ["-C", "link-args=-Objc -all_load"]
# This cfg will reduce the size of `windows::core::Error` from 16 bytes to 4 bytes
[target.'cfg(target_os = "windows")']
rustflags = ["--cfg", "windows_slim_errors"]
Generated
+828 -1502
View File
File diff suppressed because it is too large Load Diff
-6
View File
@@ -363,7 +363,6 @@ heed = { version = "0.20.1", features = ["read-txn-no-tls"] }
hex = "0.4.3"
html5ever = "0.27.0"
hyper = "0.14"
http = "1.1"
ignore = "0.4.22"
image = "0.25.1"
indexmap = { version = "1.6.2", features = ["serde"] }
@@ -372,7 +371,6 @@ itertools = "0.13.0"
jsonwebtoken = "9.3"
libc = "0.2"
linkify = "0.10.0"
livekit = { git = "https://github.com/zed-industries/rust-sdks", rev="4262308983646ab5b0e0802c3d8bc52154f99aab", features = ["dispatcher", "services-dispatcher", "rustls-tls-native-roots"], default-features = false }
log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] }
markup5ever_rcdom = "0.3.0"
nanoid = "0.4"
@@ -551,10 +549,6 @@ features = [
"Win32_UI_WindowsAndMessaging",
]
# TODO livekit https://github.com/RustAudio/cpal/pull/891
[patch.crates-io]
cpal = { git = "https://github.com/zed-industries/cpal", rev = "fd8bc2fd39f1f5fdee5a0690656caff9a26d9d50" }
[profile.dev]
split-debuginfo = "unpacked"
debug = "limited"
-1
View File
@@ -27,7 +27,6 @@ anyhow.workspace = true
audio.workspace = true
client.workspace = true
collections.workspace = true
feature_flags.workspace = true
fs.workspace = true
futures.workspace = true
gpui.workspace = true
-9
View File
@@ -18,11 +18,6 @@ use room::Event;
use settings::Settings;
use std::sync::Arc;
#[cfg(not(target_os = "windows"))]
pub use live_kit_client::play_remote_video_track;
pub use live_kit_client::{
track::RemoteVideoTrack, RemoteVideoTrackView, RemoteVideoTrackViewEvent,
};
pub use participant::ParticipantLocation;
pub use room::Room;
@@ -31,10 +26,6 @@ struct GlobalActiveCall(Model<ActiveCall>);
impl Global for GlobalActiveCall {}
pub fn init(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut AppContext) {
live_kit_client::init(
cx.background_executor().dispatcher.clone(),
cx.http_client(),
);
CallSettings::register(cx);
let active_call = cx.new_model(|cx| ActiveCall::new(client, user_store, cx));
+7 -21
View File
@@ -1,17 +1,13 @@
#![cfg_attr(target_os = "windows", allow(unused))]
use anyhow::{anyhow, Result};
use client::{proto, ParticipantIndex, User};
use client::ParticipantIndex;
use client::{proto, User};
use collections::HashMap;
use gpui::WeakModel;
use live_kit_client::AudioStream;
pub use live_kit_client::Frame;
pub use live_kit_client::{RemoteAudioTrack, RemoteVideoTrack};
use project::Project;
use std::sync::Arc;
#[cfg(not(target_os = "windows"))]
pub use live_kit_client::id::TrackSid;
pub use live_kit_client::track::{RemoteAudioTrack, RemoteVideoTrack};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ParticipantLocation {
SharedProject { project_id: u64 },
@@ -43,6 +39,7 @@ pub struct LocalParticipant {
pub role: proto::ChannelRole,
}
#[derive(Clone, Debug)]
pub struct RemoteParticipant {
pub user: Arc<User>,
pub peer_id: proto::PeerId,
@@ -52,17 +49,6 @@ pub struct RemoteParticipant {
pub participant_index: ParticipantIndex,
pub muted: bool,
pub speaking: bool,
#[cfg(not(target_os = "windows"))]
pub video_tracks: HashMap<TrackSid, RemoteVideoTrack>,
#[cfg(not(target_os = "windows"))]
pub audio_tracks: HashMap<TrackSid, (RemoteAudioTrack, AudioStream)>,
}
impl RemoteParticipant {
pub fn has_video_tracks(&self) -> bool {
#[cfg(not(target_os = "windows"))]
return !self.video_tracks.is_empty();
#[cfg(target_os = "windows")]
return false;
}
pub video_tracks: HashMap<live_kit_client::Sid, Arc<RemoteVideoTrack>>,
pub audio_tracks: HashMap<live_kit_client::Sid, Arc<RemoteAudioTrack>>,
}
+375 -439
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,6 +1,3 @@
// todo(windows): Actually run the tests
#![cfg(not(target_os = "windows"))]
use std::sync::Arc;
use call::Room;
+6 -18
View File
@@ -107,9 +107,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
});
assert!(project_b.read_with(cx_b, |project, cx| project.is_read_only(cx)));
assert!(editor_b.update(cx_b, |e, cx| e.read_only(cx)));
cx_b.update(|cx_b| {
assert!(room_b.read_with(cx_b, |room, cx| !room.can_use_microphone(cx)));
});
assert!(room_b.read_with(cx_b, |room, _| !room.can_use_microphone()));
assert!(room_b
.update(cx_b, |room, cx| room.share_microphone(cx))
.await
@@ -135,9 +133,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
assert!(editor_b.update(cx_b, |editor, cx| !editor.read_only(cx)));
// B sees themselves as muted, and can unmute.
cx_b.update(|cx_b| {
assert!(room_b.read_with(cx_b, |room, cx| room.can_use_microphone(cx)));
});
assert!(room_b.read_with(cx_b, |room, _| room.can_use_microphone()));
room_b.read_with(cx_b, |room, _| assert!(room.is_muted()));
room_b.update(cx_b, |room, cx| room.toggle_mute(cx));
cx_a.run_until_parked();
@@ -230,9 +226,7 @@ async fn test_channel_requires_zed_cla(cx_a: &mut TestAppContext, cx_b: &mut Tes
let room_b = cx_b
.read(ActiveCall::global)
.update(cx_b, |call, _| call.room().unwrap().clone());
cx_b.update(|cx_b| {
assert!(room_b.read_with(cx_b, |room, cx| !room.can_use_microphone(cx)));
});
assert!(room_b.read_with(cx_b, |room, _| !room.can_use_microphone()));
// A tries to grant write access to B, but cannot because B has not
// yet signed the zed CLA.
@@ -250,9 +244,7 @@ async fn test_channel_requires_zed_cla(cx_a: &mut TestAppContext, cx_b: &mut Tes
.unwrap_err();
cx_a.run_until_parked();
assert!(room_b.read_with(cx_b, |room, _| !room.can_share_projects()));
cx_b.update(|cx_b| {
assert!(room_b.read_with(cx_b, |room, cx| !room.can_use_microphone(cx)));
});
assert!(room_b.read_with(cx_b, |room, _| !room.can_use_microphone()));
// A tries to grant write access to B, but cannot because B has not
// yet signed the zed CLA.
@@ -270,9 +262,7 @@ async fn test_channel_requires_zed_cla(cx_a: &mut TestAppContext, cx_b: &mut Tes
.unwrap();
cx_a.run_until_parked();
assert!(room_b.read_with(cx_b, |room, _| !room.can_share_projects()));
cx_b.update(|cx_b| {
assert!(room_b.read_with(cx_b, |room, cx| room.can_use_microphone(cx)));
});
assert!(room_b.read_with(cx_b, |room, _| room.can_use_microphone()));
// User B signs the zed CLA.
server
@@ -297,7 +287,5 @@ async fn test_channel_requires_zed_cla(cx_a: &mut TestAppContext, cx_b: &mut Tes
.unwrap();
cx_a.run_until_parked();
assert!(room_b.read_with(cx_b, |room, _| room.can_share_projects()));
cx_b.update(|cx_b| {
assert!(room_b.read_with(cx_b, |room, cx| room.can_use_microphone(cx)));
});
assert!(room_b.read_with(cx_b, |room, _| room.can_use_microphone()));
}
+7 -6
View File
@@ -9,9 +9,10 @@ use collab_ui::{
use editor::{Editor, ExcerptRange, MultiBuffer};
use gpui::{
point, BackgroundExecutor, BorrowAppContext, Context, Entity, SharedString, TestAppContext,
TestScreenCaptureSource, View, VisualContext, VisualTestContext,
View, VisualContext, VisualTestContext,
};
use language::Capability;
use live_kit_client::MacOSDisplay;
use project::WorktreeSettings;
use rpc::proto::PeerId;
use serde_json::json;
@@ -428,17 +429,17 @@ async fn test_basic_following(
);
// Client B activates an external window, which causes a new screen-sharing item to be added to the pane.
let display = TestScreenCaptureSource::new();
let display = MacOSDisplay::new();
active_call_b
.update(cx_b, |call, cx| call.set_location(None, cx))
.await
.unwrap();
cx_b.set_screen_capture_sources(vec![display]);
active_call_b
.update(cx_b, |call, cx| {
call.room()
.unwrap()
.update(cx, |room, cx| room.share_screen(cx))
call.room().unwrap().update(cx, |room, cx| {
room.set_display_sources(vec![display.clone()]);
room.share_screen(cx)
})
})
.await
.unwrap();
+14 -13
View File
@@ -15,7 +15,7 @@ use futures::{channel::mpsc, StreamExt as _};
use git::repository::GitFileStatus;
use gpui::{
px, size, AppContext, BackgroundExecutor, Model, Modifiers, MouseButton, MouseDownEvent,
TestAppContext, TestScreenCaptureSource, UpdateGlobal,
TestAppContext, UpdateGlobal,
};
use language::{
language_settings::{
@@ -24,6 +24,7 @@ use language::{
tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticEntry, FakeLspAdapter,
Language, LanguageConfig, LanguageMatcher, LineEnding, OffsetRangeExt, Point, Rope,
};
use live_kit_client::MacOSDisplay;
use lsp::LanguageServerId;
use parking_lot::Mutex;
use project::lsp_store::FormatTarget;
@@ -240,15 +241,15 @@ async fn test_basic_calls(
);
// User A shares their screen
let display = TestScreenCaptureSource::new();
let display = MacOSDisplay::new();
let events_b = active_call_events(cx_b);
let events_c = active_call_events(cx_c);
cx_a.set_screen_capture_sources(vec![display]);
active_call_a
.update(cx_a, |call, cx| {
call.room()
.unwrap()
.update(cx, |room, cx| room.share_screen(cx))
call.room().unwrap().update(cx, |room, cx| {
room.set_display_sources(vec![display.clone()]);
room.share_screen(cx)
})
})
.await
.unwrap();
@@ -1941,7 +1942,7 @@ async fn test_mute_deafen(
room_a.read_with(cx_a, |room, _| assert!(!room.is_muted()));
room_b.read_with(cx_b, |room, _| assert!(!room.is_muted()));
// Users A and B are both unmuted.
// Users A and B are both muted.
assert_eq!(
participant_audio_state(&room_a, cx_a),
&[ParticipantAudioState {
@@ -2073,7 +2074,7 @@ async fn test_mute_deafen(
audio_tracks_playing: participant
.audio_tracks
.values()
.map(|(track, _)| track.rtc_track().enabled())
.map(|track| track.is_playing())
.collect(),
})
.collect::<Vec<_>>()
@@ -6056,13 +6057,13 @@ async fn test_join_call_after_screen_was_shared(
assert_eq!(call_b.calling_user.github_login, "user_a");
// User A shares their screen
let display = TestScreenCaptureSource::new();
cx_a.set_screen_capture_sources(vec![display]);
let display = MacOSDisplay::new();
active_call_a
.update(cx_a, |call, cx| {
call.room()
.unwrap()
.update(cx, |room, cx| room.share_screen(cx))
call.room().unwrap().update(cx, |room, cx| {
room.set_display_sources(vec![display.clone()]);
room.share_screen(cx)
})
})
.await
.unwrap();
+3 -3
View File
@@ -47,7 +47,7 @@ use workspace::{Workspace, WorkspaceStore};
pub struct TestServer {
pub app_state: Arc<AppState>,
pub test_live_kit_server: Arc<live_kit_client::test::TestServer>,
pub test_live_kit_server: Arc<live_kit_client::TestServer>,
server: Arc<Server>,
next_github_user_id: i32,
connection_killers: Arc<Mutex<HashMap<PeerId, Arc<AtomicBool>>>>,
@@ -89,7 +89,7 @@ impl TestServer {
TestDb::sqlite(deterministic.clone())
};
let live_kit_server_id = NEXT_LIVE_KIT_SERVER_ID.fetch_add(1, SeqCst);
let live_kit_server = live_kit_client::test::TestServer::create(
let live_kit_server = live_kit_client::TestServer::create(
format!("http://livekit.{}.test", live_kit_server_id),
format!("devkey-{}", live_kit_server_id),
format!("secret-{}", live_kit_server_id),
@@ -499,7 +499,7 @@ impl TestServer {
pub async fn build_app_state(
test_db: &TestDb,
live_kit_test_server: &live_kit_client::test::TestServer,
live_kit_test_server: &live_kit_client::TestServer,
executor: Executor,
) -> Arc<AppState> {
Arc::new(AppState {
+3 -2
View File
@@ -474,10 +474,11 @@ impl CollabPanel {
project_id: project.id,
worktree_root_names: project.worktree_root_names.clone(),
host_user_id: participant.user.id,
is_last: projects.peek().is_none() && !participant.has_video_tracks(),
is_last: projects.peek().is_none()
&& participant.video_tracks.is_empty(),
});
}
if participant.has_video_tracks() {
if !participant.video_tracks.is_empty() {
self.entries.push(ListEntry::ParticipantScreen {
peer_id: Some(participant.peer_id),
is_last: true,
-1
View File
@@ -48,7 +48,6 @@ mod macos {
fn generate_dispatch_bindings() {
println!("cargo:rustc-link-lib=framework=System");
println!("cargo:rustc-link-lib=framework=ScreenCaptureKit");
println!("cargo:rerun-if-changed=src/platform/mac/dispatch.h");
let bindings = bindgen::Builder::default()
+2 -9
View File
@@ -33,8 +33,8 @@ use crate::{
Entity, EventEmitter, ForegroundExecutor, Global, KeyBinding, Keymap, Keystroke, LayoutId,
Menu, MenuItem, OwnedMenu, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point,
PromptBuilder, PromptHandle, PromptLevel, Render, RenderablePromptHandle, Reservation,
ScreenCaptureSource, SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextSystem,
View, ViewContext, Window, WindowAppearance, WindowContext, WindowHandle, WindowId,
SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, View, ViewContext,
Window, WindowAppearance, WindowContext, WindowHandle, WindowId,
};
mod async_context;
@@ -599,13 +599,6 @@ impl AppContext {
self.platform.primary_display()
}
/// Returns a list of available screen capture sources.
pub fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
self.platform.screen_capture_sources()
}
/// Returns the display with the given ID, if one exists.
pub fn find_display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
self.displays()
+2 -8
View File
@@ -4,8 +4,8 @@ use crate::{
Element, Empty, Entity, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Model,
ModelContext, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent,
MouseUpEvent, Pixels, Platform, Point, Render, Result, Size, Task, TestDispatcher,
TestPlatform, TestScreenCaptureSource, TestWindow, TextSystem, View, ViewContext,
VisualContext, WindowBounds, WindowContext, WindowHandle, WindowOptions,
TestPlatform, TestWindow, TextSystem, View, ViewContext, VisualContext, WindowBounds,
WindowContext, WindowHandle, WindowOptions,
};
use anyhow::{anyhow, bail};
use futures::{channel::oneshot, Stream, StreamExt};
@@ -287,12 +287,6 @@ impl TestAppContext {
self.test_window(window_handle).simulate_resize(size);
}
/// Causes the given sources to be returned if the application queries for screen
/// capture sources.
pub fn set_screen_capture_sources(&self, sources: Vec<TestScreenCaptureSource>) {
self.test_platform.set_screen_capture_sources(sources);
}
/// Returns all windows open in the test.
pub fn windows(&self) -> Vec<AnyWindowHandle> {
self.app.borrow().windows().clone()
-5
View File
@@ -704,11 +704,6 @@ pub struct Bounds<T: Clone + Default + Debug> {
pub size: Size<T>,
}
/// Create a bounds with the given origin and size
pub fn bounds<T: Clone + Default + Debug>(origin: Point<T>, size: Size<T>) -> Bounds<T> {
Bounds { origin, size }
}
impl Bounds<Pixels> {
/// Generate a centered bounds for the given display or primary display if none is provided
pub fn centered(display_id: Option<DisplayId>, size: Size<Pixels>, cx: &AppContext) -> Self {
-26
View File
@@ -70,9 +70,6 @@ pub(crate) use test::*;
#[cfg(target_os = "windows")]
pub(crate) use windows::*;
#[cfg(any(test, feature = "test-support"))]
pub use test::TestScreenCaptureSource;
#[cfg(target_os = "macos")]
pub(crate) fn current_platform(headless: bool) -> Rc<dyn Platform> {
Rc::new(MacPlatform::new(headless))
@@ -152,10 +149,6 @@ pub(crate) trait Platform: 'static {
None
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>>;
fn open_window(
&self,
handle: AnyWindowHandle,
@@ -235,25 +228,6 @@ pub trait PlatformDisplay: Send + Sync + Debug {
}
}
/// A source of on-screen video content that can be captured.
pub trait ScreenCaptureSource {
/// Returns the video resolution of this source.
fn resolution(&self) -> Result<Size<Pixels>>;
/// Start capture video from this source, invoking the given callback
/// with each frame.
fn stream(
&self,
frame_callback: Box<dyn Fn(ScreenCaptureFrame)>,
) -> oneshot::Receiver<Result<Box<dyn ScreenCaptureStream>>>;
}
/// A video stream captured from a screen.
pub trait ScreenCaptureStream {}
/// A frame of video captured from a screen.
pub struct ScreenCaptureFrame(pub PlatformScreenCaptureFrame);
/// An opaque identifier for a hardware display
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
pub struct DisplayId(pub(crate) u32);
-2
View File
@@ -20,5 +20,3 @@ pub(crate) use text_system::*;
pub(crate) use wayland::*;
#[cfg(feature = "x11")]
pub(crate) use x11::*;
pub(crate) type PlatformScreenCaptureFrame = ();
+2 -10
View File
@@ -35,8 +35,8 @@ use crate::{
px, Action, AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DisplayId,
ForegroundExecutor, Keymap, Keystroke, LinuxDispatcher, Menu, MenuItem, Modifiers, OwnedMenu,
PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformInputHandler, PlatformTextSystem,
PlatformWindow, Point, PromptLevel, Result, ScreenCaptureSource, SemanticVersion, SharedString,
Size, Task, WindowAppearance, WindowOptions, WindowParams,
PlatformWindow, Point, PromptLevel, Result, SemanticVersion, SharedString, Size, Task,
WindowAppearance, WindowOptions, WindowParams,
};
pub(crate) const SCROLL_LINES: f32 = 3.0;
@@ -242,14 +242,6 @@ impl<P: LinuxClient + 'static> Platform for P {
self.displays()
}
fn screen_capture_sources(
&self,
) -> oneshot::Receiver<Result<Vec<Box<dyn ScreenCaptureSource>>>> {
let (mut tx, rx) = oneshot::channel();
tx.send(Err(anyhow!("screen capture not implemented"))).ok();
rx
}
fn active_window(&self) -> Option<AnyWindowHandle> {
self.active_window()
}

Some files were not shown because too many files have changed in this diff Show More