diff --git a/crates/capture/src/main.rs b/crates/capture/src/main.rs index c34f451e41..9398322c69 100644 --- a/crates/capture/src/main.rs +++ b/crates/capture/src/main.rs @@ -38,6 +38,11 @@ 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, diff --git a/crates/live_kit/LiveKitBridge/Package.resolved b/crates/live_kit/LiveKitBridge/Package.resolved index b19e2980a4..93c1738b06 100644 --- a/crates/live_kit/LiveKitBridge/Package.resolved +++ b/crates/live_kit/LiveKitBridge/Package.resolved @@ -6,7 +6,7 @@ "repositoryURL": "https://github.com/livekit/client-sdk-swift.git", "state": { "branch": null, - "revision": "5cc3c001779ab147199ce3ea0dce465b846368b4", + "revision": "a90ecba800f65bebfc31f5c9c59f635c8587ec7e", "version": null } }, @@ -42,8 +42,8 @@ "repositoryURL": "https://github.com/apple/swift-protobuf.git", "state": { "branch": null, - "revision": "b8230909dedc640294d7324d37f4c91ad3dcf177", - "version": "1.20.1" + "revision": "88c7d15e1242fdb6ecbafbc7926426a19be1e98a", + "version": "1.20.2" } } ] diff --git a/crates/live_kit/LiveKitBridge/Package.swift b/crates/live_kit/LiveKitBridge/Package.swift index 76e528bda9..850e3459b4 100644 --- a/crates/live_kit/LiveKitBridge/Package.swift +++ b/crates/live_kit/LiveKitBridge/Package.swift @@ -15,7 +15,7 @@ let package = Package( targets: ["LiveKitBridge"]), ], dependencies: [ - .package(url: "https://github.com/livekit/client-sdk-swift.git", revision: "5cc3c001779ab147199ce3ea0dce465b846368b4"), + .package(url: "https://github.com/livekit/client-sdk-swift.git", revision: "a90ecba800f65bebfc31f5c9c59f635c8587ec7e"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/crates/live_kit/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift b/crates/live_kit/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift index f59b829203..c718f27761 100644 --- a/crates/live_kit/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift +++ b/crates/live_kit/LiveKitBridge/Sources/LiveKitBridge/LiveKitBridge.swift @@ -103,3 +103,12 @@ public func LKVideoTrackAddRenderer(track: UnsafeRawPointer, renderer: UnsafeRaw let renderer = Unmanaged.fromOpaque(renderer).takeRetainedValue() track.add(videoRenderer: renderer) } + +@_cdecl("LKDisplaySources") +public func LKDisplaySources(data: UnsafeRawPointer, callback: @escaping @convention(c) (UnsafeRawPointer, CFArray?, CFString?) -> Void) { + MacOSScreenCapturer.displaySources().then { displaySources in + callback(data, displaySources as CFArray, nil) + }.catch { error in + callback(data, nil, error.localizedDescription as CFString) + } +} diff --git a/crates/live_kit/src/live_kit.rs b/crates/live_kit/src/live_kit.rs index 59ce860a78..79ee645041 100644 --- a/crates/live_kit/src/live_kit.rs +++ b/crates/live_kit/src/live_kit.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Context, Result}; use core_foundation::{ - array::CFArray, + array::{CFArray, CFArrayRef}, base::{TCFType, TCFTypeRef}, dictionary::CFDictionary, number::CFNumber, @@ -56,6 +56,14 @@ 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( + callback_data: *mut c_void, + sources: CFArrayRef, + error: CFStringRef, + ), + ); } pub struct Room { @@ -274,3 +282,32 @@ pub fn list_windows() -> Vec { .collect() } } + +pub struct MacOSDisplay(*const c_void); + +pub fn display_sources() -> impl Future>> { + extern "C" fn callback(tx: *mut c_void, sources: CFArrayRef, error: CFStringRef) { + unsafe { + let tx = Box::from_raw(tx as *mut oneshot::Sender>>); + + if sources.is_null() { + 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 (tx, rx) = oneshot::channel(); + + unsafe { + LKDisplaySources(Box::into_raw(Box::new(tx)) as *mut _, callback); + } + + async move { rx.await.unwrap() } +}