WIP: Getting a big black window, then a crash

Nathan Sobo created

Change summary

crates/capture/src/main.rs                                              | 17 
crates/live_kit/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift |  8 
crates/live_kit/src/live_kit.rs                                         | 24 
3 files changed, 33 insertions(+), 16 deletions(-)

Detailed changes

crates/capture/src/main.rs 🔗

@@ -38,11 +38,6 @@ fn main() {
         let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap();
 
         cx.spawn(|mut cx| async move {
-            match live_kit::display_sources().await {
-                Ok(sources) => println!("found {} sources", sources.len()),
-                Err(error) => println!("error finding display sources {}", error),
-            }
-
             let user1_token = live_kit_token::create_token(
                 &live_kit_key,
                 &live_kit_secret,
@@ -64,12 +59,14 @@ fn main() {
             room2.connect(&live_kit_url, &user2_token).await.unwrap();
             cx.add_window(Default::default(), |cx| ScreenCaptureView::new(room2, cx));
 
-            let windows = live_kit::list_windows();
-            let window = windows
-                .iter()
-                .find(|w| w.owner_name.as_deref() == Some("Safari"))
+            let display = live_kit::display_sources()
+                .await
+                .unwrap()
+                .into_iter()
+                .next()
                 .unwrap();
-            let track = LocalVideoTrack::screen_share_for_window(window.id);
+
+            let track = LocalVideoTrack::screen_share_for_display(display);
             room1.publish_video_track(&track).await.unwrap();
         })
         .detach();

crates/live_kit/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift 🔗

@@ -92,6 +92,14 @@ public func LKCreateScreenShareTrackForWindow(windowId: uint32) -> UnsafeMutable
     return Unmanaged.passRetained(track).toOpaque()
 }
 
+@_cdecl("LKCreateScreenShareTrackForDisplay")
+public func LKCreateScreenShareTrackForDisplay(display: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer {
+    let display = Unmanaged<MacOSDisplay>.fromOpaque(display).takeRetainedValue()
+    print("!!!!!!!!!! display id", display.displayID)
+    let track = LocalVideoTrack.createMacOSScreenShareTrack(source: display)
+    return Unmanaged.passRetained(track).toOpaque()
+}
+
 @_cdecl("LKVideoRendererCreate")
 public func LKVideoRendererCreate(data: UnsafeRawPointer, onFrame: @escaping @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void, onDrop: @escaping @convention(c) (UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
     Unmanaged.passRetained(LKVideoRenderer(data: data, onFrame: onFrame, onDrop: onDrop)).toOpaque()

crates/live_kit/src/live_kit.rs 🔗

@@ -55,7 +55,6 @@ extern "C" {
 
     fn LKVideoTrackAddRenderer(track: *const c_void, renderer: *const c_void);
 
-    fn LKCreateScreenShareTrackForWindow(windowId: u32) -> *const c_void;
     fn LKDisplaySources(
         callback_data: *mut c_void,
         callback: extern "C" fn(
@@ -64,6 +63,8 @@ extern "C" {
             error: CFStringRef,
         ),
     );
+    fn LKCreateScreenShareTrackForWindow(windowId: u32) -> *const c_void;
+    fn LKCreateScreenShareTrackForDisplay(display: *const c_void) -> *const c_void;
 }
 
 pub struct Room {
@@ -196,6 +197,13 @@ impl LocalVideoTrack {
     pub fn screen_share_for_window(window_id: u32) -> Self {
         Self(unsafe { LKCreateScreenShareTrackForWindow(window_id) })
     }
+
+    pub fn screen_share_for_display(display: MacOSDisplay) -> Self {
+        let ptr = display.0;
+        let this = Self(unsafe { LKCreateScreenShareTrackForDisplay(ptr) });
+        std::mem::forget(display);
+        this
+    }
 }
 
 impl Drop for LocalVideoTrack {
@@ -285,6 +293,12 @@ pub fn list_windows() -> Vec<WindowInfo> {
 
 pub struct MacOSDisplay(*const c_void);
 
+impl Drop for MacOSDisplay {
+    fn drop(&mut self) {
+        unsafe { LKRelease(self.0) }
+    }
+}
+
 pub fn display_sources() -> impl Future<Output = Result<Vec<MacOSDisplay>>> {
     extern "C" fn callback(tx: *mut c_void, sources: CFArrayRef, error: CFStringRef) {
         unsafe {
@@ -294,11 +308,9 @@ pub fn display_sources() -> impl Future<Output = Result<Vec<MacOSDisplay>>> {
                 let _ = tx.send(Err(anyhow!("{}", CFString::wrap_under_get_rule(error))));
             } else {
                 let sources = CFArray::wrap_under_get_rule(sources);
-                let sources = sources
-                    .into_iter()
-                    .map(|source| MacOSDisplay(*source))
-                    .collect();
-                let _ = tx.send(Ok(sources));
+                let sources_vec = sources.iter().map(|source| MacOSDisplay(*source)).collect();
+                let _ = tx.send(Ok(sources_vec));
+                std::mem::forget(sources); // HACK: If I drop the CFArray, all the objects inside it get dropped and we get issues accessing the display later.
             }
         }
     }