WIP: Use audio support to send live data

Mikayla Maki created

Change summary

crates/live_kit_client/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift | 29 
crates/live_kit_client/examples/test_app.rs                                    |  8 
crates/live_kit_client/src/prod.rs                                             | 33 
crates/live_kit_client/src/test.rs                                             |  4 
4 files changed, 62 insertions(+), 12 deletions(-)

Detailed changes

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

@@ -183,14 +183,6 @@ public func LKRoomVideoTracksForRemoteParticipant(room: UnsafeRawPointer, partic
     return nil;
 }
 
-@_cdecl("LKCreateScreenShareTrackForDisplay")
-public func LKCreateScreenShareTrackForDisplay(display: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer {
-    let display = Unmanaged<MacOSDisplay>.fromOpaque(display).takeUnretainedValue()
-    let track = LocalVideoTrack.createMacOSScreenShareTrack(source: display, preferredMethod: .legacy)
-    return Unmanaged.passRetained(track).toOpaque()
-}
-
-
 @_cdecl("LKLocalAudioTrackCreateTrack")
 public func LKLocalAudioTrackCreateTrack() -> UnsafeMutableRawPointer {
     let track = LocalAudioTrack.createTrack(options: AudioCaptureOptions(
@@ -201,6 +193,27 @@ public func LKLocalAudioTrackCreateTrack() -> UnsafeMutableRawPointer {
     return Unmanaged.passRetained(track).toOpaque()
 }
 
+
+@_cdecl("LKCreateScreenShareTrackForDisplay")
+public func LKCreateScreenShareTrackForDisplay(display: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer {
+    let display = Unmanaged<MacOSDisplay>.fromOpaque(display).takeUnretainedValue()
+    let track = LocalVideoTrack.createMacOSScreenShareTrack(source: display, preferredMethod: .legacy)
+    return Unmanaged.passRetained(track).toOpaque()
+}
+
+@_cdecl("LKRemoteAudioTrackStart")
+public func LKRemoteAudioTrackStart(track: UnsafeRawPointer, onStart: @escaping @convention(c) (UnsafeRawPointer, Bool) -> Void, callbackData: UnsafeRawPointer) {
+    let track = Unmanaged<Track>.fromOpaque(track).takeUnretainedValue() as! RemoteAudioTrack
+
+    track.start().then { success in
+        onStart(callbackData, success)
+    }
+    .catch { _ in
+        onStart(callbackData, false)
+    }
+}
+
+
 @_cdecl("LKVideoRendererCreate")
 public func LKVideoRendererCreate(data: UnsafeRawPointer, onFrame: @escaping @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Bool, onDrop: @escaping @convention(c) (UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
     Unmanaged.passRetained(LKVideoRenderer(data: data, onFrame: onFrame, onDrop: onDrop)).toOpaque()

crates/live_kit_client/examples/test_app.rs 🔗

@@ -1,3 +1,6 @@
+
+use std::time::Duration;
+
 use futures::StreamExt;
 use gpui::{actions, keymap_matcher::Binding, Menu, MenuItem};
 use live_kit_client::{LocalVideoTrack, RemoteVideoTrackUpdate, Room, LocalAudioTrack, RemoteAudioTrackUpdate};
@@ -69,6 +72,11 @@ fn main() {
                 panic!("unexpected message");
             }
 
+            let res = room_b.remote_audio_tracks("test-participant-1")[0].start().await;
+            println!("Attempting to start: {:?}", res);
+            let timer = cx.background().timer(Duration::from_secs(10));
+            timer.await;
+
             let remote_audio_track = room_b
                 .remote_audio_tracks("test-participant-1")
                 .pop()

crates/live_kit_client/src/prod.rs 🔗

@@ -84,7 +84,17 @@ extern "C" {
     ) -> *const c_void;
 
     fn LKRemoteAudioTrackGetSid(track: *const c_void) -> CFStringRef;
-    fn LKVideoTrackAddRenderer(track: *const c_void, renderer: *const c_void);
+    fn LKRemoteAudioTrackStart(
+        track: *const c_void,
+        callback: extern "C" fn(*mut c_void, bool),
+        callback_data: *mut c_void
+    );
+
+    fn LKVideoTrackAddRenderer(
+        track: *const c_void,
+        renderer: *const c_void
+       ,
+    );
     fn LKRemoteVideoTrackGetSid(track: *const c_void) -> CFStringRef;
 
     fn LKDisplaySources(
@@ -307,7 +317,6 @@ impl Room {
         }
     }
 
-
     pub fn remote_audio_track_updates(&self) -> mpsc::UnboundedReceiver<RemoteAudioTrackUpdate> {
         let (tx, rx) = mpsc::unbounded();
         self.remote_audio_track_subscribers.lock().push(tx);
@@ -552,8 +561,25 @@ impl RemoteAudioTrack {
     pub fn publisher_id(&self) -> &str {
         &self.publisher_id
     }
-}
 
+    pub fn start(&self) -> futures::channel::oneshot::Receiver<bool> {
+        let (tx, rx) = futures::channel::oneshot::channel();
+
+        extern "C" fn on_start(callback_data: *mut c_void, success: bool) {
+            unsafe {
+                let tx =
+                    Box::from_raw(callback_data as *mut futures::channel::oneshot::Sender<bool>);
+                tx.send(success).ok();
+            }
+        }
+
+        unsafe {
+            LKRemoteAudioTrackStart(self.native_track, on_start, Box::into_raw(Box::new(tx)) as *mut c_void)
+        }
+
+        rx
+    }
+}
 
 #[derive(Debug)]
 pub struct RemoteVideoTrack {
@@ -639,7 +665,6 @@ pub enum RemoteAudioTrackUpdate {
     Unsubscribed { publisher_id: Sid, track_id: Sid },
 }
 
-
 pub struct MacOSDisplay(*const c_void);
 
 impl MacOSDisplay {

crates/live_kit_client/src/test.rs 🔗

@@ -476,6 +476,10 @@ impl RemoteAudioTrack {
     pub fn publisher_id(&self) -> &str {
         &self.publisher_id
     }
+
+    pub fn start(&self)  -> futures::channel::oneshot::Receiver<bool> {
+        todo!();
+    }
 }
 
 #[derive(Clone)]