mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 01:34:02 +00:00
Add ability to get a screen share track for a window
And also list windows
This commit is contained in:
parent
5347c7d678
commit
7bf64ec23e
5 changed files with 93 additions and 23 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2941,6 +2941,7 @@ name = "live_kit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
|
"core-graphics",
|
||||||
"futures",
|
"futures",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -7,7 +7,7 @@ use gpui::{
|
||||||
platform::current::Surface,
|
platform::current::Surface,
|
||||||
Menu, MenuItem, ViewContext,
|
Menu, MenuItem, ViewContext,
|
||||||
};
|
};
|
||||||
use live_kit::Room;
|
use live_kit::{LocalVideoTrack, Room};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use media::core_video::CVImageBuffer;
|
use media::core_video::CVImageBuffer;
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
|
@ -42,13 +42,17 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let room = live_kit::Room::new();
|
let room = live_kit::Room::new();
|
||||||
cx.spawn(|cx| async move {
|
cx.foreground()
|
||||||
println!("connecting...");
|
.spawn(async move {
|
||||||
room.connect("wss://zed.livekit.cloud", &token).await;
|
println!("connecting...");
|
||||||
println!("connected!");
|
room.connect("wss://zed.livekit.cloud", &token).await;
|
||||||
drop(room);
|
let windows = live_kit::list_windows();
|
||||||
})
|
println!("connected! {:?}", windows);
|
||||||
.detach();
|
|
||||||
|
let window_id = windows.iter().next().unwrap().id;
|
||||||
|
let track = LocalVideoTrack::screen_share_for_window(window_id);
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
// cx.add_window(Default::default(), |cx| ScreenCaptureView::new(cx));
|
// cx.add_window(Default::default(), |cx| ScreenCaptureView::new(cx));
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@ doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
core-foundation = "0.9.3"
|
core-foundation = "0.9.3"
|
||||||
|
core-graphics = "0.22.3"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import LiveKit
|
import LiveKit
|
||||||
|
|
||||||
|
@_cdecl("LKRelease")
|
||||||
|
public func LKRelease(ptr: UnsafeRawPointer) {
|
||||||
|
let _ = Unmanaged<AnyObject>.fromOpaque(ptr).takeRetainedValue();
|
||||||
|
}
|
||||||
|
|
||||||
@_cdecl("LKRoomCreate")
|
@_cdecl("LKRoomCreate")
|
||||||
public func LKRoomCreate() -> UnsafeMutableRawPointer {
|
public func LKRoomCreate() -> UnsafeMutableRawPointer {
|
||||||
Unmanaged.passRetained(Room()).toOpaque()
|
Unmanaged.passRetained(Room()).toOpaque()
|
||||||
}
|
}
|
||||||
|
|
||||||
@_cdecl("LKRoomDestroy")
|
|
||||||
public func LKRoomDestroy(ptr: UnsafeRawPointer) {
|
|
||||||
let _ = Unmanaged<Room>.fromOpaque(ptr).takeRetainedValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@_cdecl("LKRoomConnect")
|
@_cdecl("LKRoomConnect")
|
||||||
public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString, callback: @escaping @convention(c) (UnsafeRawPointer) -> Void, callback_data: UnsafeRawPointer) {
|
public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString, callback: @escaping @convention(c) (UnsafeRawPointer) -> Void, callback_data: UnsafeRawPointer) {
|
||||||
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue();
|
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue();
|
||||||
|
@ -21,3 +21,9 @@ public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString
|
||||||
print(error);
|
print(error);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@_cdecl("LKCreateScreenShareTrackForWindow")
|
||||||
|
public func LKCreateScreenShareTrackForWindow(windowId: uint32) -> UnsafeMutableRawPointer {
|
||||||
|
let track = LocalVideoTrack.createMacOSScreenShareTrack(source: .window(id: windowId));
|
||||||
|
return Unmanaged.passRetained(track).toOpaque()
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
use core_foundation::{
|
use core_foundation::{
|
||||||
base::TCFType,
|
array::CFArray,
|
||||||
|
base::{TCFType, TCFTypeRef},
|
||||||
|
dictionary::CFDictionary,
|
||||||
|
number::CFNumber,
|
||||||
string::{CFString, CFStringRef},
|
string::{CFString, CFStringRef},
|
||||||
};
|
};
|
||||||
|
use core_graphics::window::{
|
||||||
|
kCGNullWindowID, kCGWindowListOptionExcludeDesktopElements, kCGWindowListOptionOnScreenOnly,
|
||||||
|
kCGWindowNumber, kCGWindowOwnerName, kCGWindowOwnerPID, CGWindowListCopyWindowInfo,
|
||||||
|
};
|
||||||
use futures::{channel::oneshot, Future};
|
use futures::{channel::oneshot, Future};
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
fn LKRelease(object: *const c_void);
|
||||||
fn LKRoomCreate() -> *const c_void;
|
fn LKRoomCreate() -> *const c_void;
|
||||||
fn LKRoomDestroy(room: *const c_void);
|
|
||||||
fn LKRoomConnect(
|
fn LKRoomConnect(
|
||||||
room: *const c_void,
|
room: *const c_void,
|
||||||
url: CFStringRef,
|
url: CFStringRef,
|
||||||
|
@ -15,17 +22,14 @@ extern "C" {
|
||||||
callback: extern "C" fn(*mut c_void) -> (),
|
callback: extern "C" fn(*mut c_void) -> (),
|
||||||
callback_data: *mut c_void,
|
callback_data: *mut c_void,
|
||||||
);
|
);
|
||||||
|
fn LKCreateScreenShareTrackForWindow(windowId: u32) -> *const c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Room {
|
pub struct Room(*const c_void);
|
||||||
native_room: *const c_void,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Room {
|
impl Room {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self(unsafe { LKRoomCreate() })
|
||||||
native_room: unsafe { LKRoomCreate() },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, url: &str, token: &str) -> impl Future<Output = ()> {
|
pub fn connect(&self, url: &str, token: &str) -> impl Future<Output = ()> {
|
||||||
|
@ -40,7 +44,7 @@ impl Room {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
LKRoomConnect(
|
LKRoomConnect(
|
||||||
self.native_room,
|
self.0,
|
||||||
url.as_concrete_TypeRef(),
|
url.as_concrete_TypeRef(),
|
||||||
token.as_concrete_TypeRef(),
|
token.as_concrete_TypeRef(),
|
||||||
did_connect,
|
did_connect,
|
||||||
|
@ -54,6 +58,60 @@ impl Room {
|
||||||
|
|
||||||
impl Drop for Room {
|
impl Drop for Room {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { LKRoomDestroy(self.native_room) }
|
unsafe { LKRelease(self.0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LocalVideoTrack(*const c_void);
|
||||||
|
|
||||||
|
impl LocalVideoTrack {
|
||||||
|
pub fn screen_share_for_window(window_id: u32) -> Self {
|
||||||
|
Self(unsafe { LKCreateScreenShareTrackForWindow(window_id) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for LocalVideoTrack {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { LKRelease(self.0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct WindowInfo {
|
||||||
|
pub id: u32,
|
||||||
|
pub owner_pid: i32,
|
||||||
|
pub owner_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_windows() -> Vec<WindowInfo> {
|
||||||
|
unsafe {
|
||||||
|
let dicts = CFArray::<CFDictionary>::wrap_under_get_rule(CGWindowListCopyWindowInfo(
|
||||||
|
kCGWindowListOptionOnScreenOnly | kCGWindowListOptionExcludeDesktopElements,
|
||||||
|
kCGNullWindowID,
|
||||||
|
));
|
||||||
|
|
||||||
|
dicts
|
||||||
|
.iter()
|
||||||
|
.map(|dict| {
|
||||||
|
let id =
|
||||||
|
CFNumber::wrap_under_get_rule(*dict.get(kCGWindowNumber.as_void_ptr()) as _)
|
||||||
|
.to_i64()
|
||||||
|
.unwrap() as u32;
|
||||||
|
|
||||||
|
let owner_pid =
|
||||||
|
CFNumber::wrap_under_get_rule(*dict.get(kCGWindowOwnerPID.as_void_ptr()) as _)
|
||||||
|
.to_i32()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let owner_name = dict
|
||||||
|
.find(kCGWindowOwnerName.as_void_ptr())
|
||||||
|
.map(|name| CFString::wrap_under_get_rule(*name as _).to_string());
|
||||||
|
WindowInfo {
|
||||||
|
id,
|
||||||
|
owner_pid,
|
||||||
|
owner_name,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue