Register to publishing of remote tracks

This commit is contained in:
Antonio Scandurra 2022-09-07 18:32:39 +02:00
parent 37ca5651ee
commit 645338cff8
3 changed files with 143 additions and 34 deletions

View file

@ -1,5 +1,7 @@
mod live_kit_token;
use std::time::Duration;
use gpui::{
actions,
elements::{Canvas, *},
@ -34,25 +36,38 @@ fn main() {
let live_kit_key = std::env::var("LIVE_KIT_KEY").unwrap();
let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap();
let token = live_kit_token::create_token(
&live_kit_key,
&live_kit_secret,
"test-room",
"test-participant",
)
.unwrap();
let room = Room::new();
let background = cx.background().clone();
cx.foreground()
.spawn(async move {
println!("connecting...");
room.connect(&live_kit_url, &token).await.unwrap();
let user1_token = live_kit_token::create_token(
&live_kit_key,
&live_kit_secret,
"test-room",
"test-participant-1",
)
.unwrap();
let room1 = Room::new("user-1 room");
room1.connect(&live_kit_url, &user1_token).await.unwrap();
let user2_token = live_kit_token::create_token(
&live_kit_key,
&live_kit_secret,
"test-room",
"test-participant-2",
)
.unwrap();
let room2 = Room::new("user-2 room");
room2.connect(&live_kit_url, &user2_token).await.unwrap();
let windows = live_kit::list_windows();
println!("connected! {:?}", windows);
let window_id = windows.iter().next().unwrap().id;
let track = LocalVideoTrack::screen_share_for_window(window_id);
room.publish_video_track(&track).await.unwrap();
room1.publish_video_track(&track).await.unwrap();
background.timer(Duration::from_secs(120)).await;
})
.detach();

View file

@ -1,40 +1,61 @@
import Foundation
import LiveKit
class LKRoomDelegate: RoomDelegate {
var data: UnsafeRawPointer
var onDidSubscribeToRemoteTrack: @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void
init(data: UnsafeRawPointer, onDidSubscribeToRemoteTrack: @escaping @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void) {
self.data = data
self.onDidSubscribeToRemoteTrack = onDidSubscribeToRemoteTrack
}
func room(_ room: Room, participant: RemoteParticipant, didSubscribe publication: RemoteTrackPublication, track: Track) {
self.onDidSubscribeToRemoteTrack(self.data, Unmanaged.passRetained(track).toOpaque())
}
}
@_cdecl("LKRelease")
public func LKRelease(ptr: UnsafeRawPointer) {
let _ = Unmanaged<AnyObject>.fromOpaque(ptr).takeRetainedValue();
let _ = Unmanaged<AnyObject>.fromOpaque(ptr).takeRetainedValue()
}
@_cdecl("LKRoomDelegateCreate")
public func LKRoomDelegateCreate(data: UnsafeRawPointer, onDidSubscribeToRemoteTrack: @escaping @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
let delegate = LKRoomDelegate(data: data, onDidSubscribeToRemoteTrack: onDidSubscribeToRemoteTrack)
return Unmanaged.passRetained(delegate).toOpaque()
}
@_cdecl("LKRoomCreate")
public func LKRoomCreate() -> UnsafeMutableRawPointer {
Unmanaged.passRetained(Room()).toOpaque()
public func LKRoomCreate(delegate: UnsafeRawPointer) -> UnsafeMutableRawPointer {
let delegate = Unmanaged<LKRoomDelegate>.fromOpaque(delegate).takeUnretainedValue()
return Unmanaged.passRetained(Room(delegate: delegate)).toOpaque()
}
@_cdecl("LKRoomConnect")
public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue();
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
room.connect(url as String, token as String).then { _ in
callback(callback_data, UnsafeRawPointer(nil) as! CFString?);
callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
}.catch { error in
callback(callback_data, error.localizedDescription as CFString);
};
callback(callback_data, error.localizedDescription as CFString)
}
}
@_cdecl("LKRoomPublishVideoTrack")
public func LKRoomPublishVideoTrack(room: UnsafeRawPointer, track: UnsafeRawPointer, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue();
let track = Unmanaged<LocalVideoTrack>.fromOpaque(track).takeUnretainedValue();
let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
let track = Unmanaged<LocalVideoTrack>.fromOpaque(track).takeUnretainedValue()
room.localParticipant?.publishVideoTrack(track: track).then { _ in
callback(callback_data, UnsafeRawPointer(nil) as! CFString?);
callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
}.catch { error in
callback(callback_data, error.localizedDescription as CFString);
};
callback(callback_data, error.localizedDescription as CFString)
}
}
@_cdecl("LKCreateScreenShareTrackForWindow")
public func LKCreateScreenShareTrackForWindow(windowId: uint32) -> UnsafeMutableRawPointer {
let track = LocalVideoTrack.createMacOSScreenShareTrack(source: .window(id: windowId));
let track = LocalVideoTrack.createMacOSScreenShareTrack(source: .window(id: windowId))
return Unmanaged.passRetained(track).toOpaque()
}

View file

@ -11,34 +11,56 @@ use core_graphics::window::{
kCGWindowNumber, kCGWindowOwnerName, kCGWindowOwnerPID, CGWindowListCopyWindowInfo,
};
use futures::{channel::oneshot, Future};
use std::ffi::c_void;
use std::{
ffi::c_void,
sync::{Arc, Weak},
};
extern "C" {
fn LKRelease(object: *const c_void);
fn LKRoomCreate() -> *const c_void;
fn LKRoomDelegateCreate(
callback_data: *const c_void,
on_did_subscribe_to_remote_track: extern "C" fn(
callback_data: *mut c_void,
remote_track: *const c_void,
),
) -> *const c_void;
fn LKRoomCreate(delegate: *const c_void) -> *const c_void;
fn LKRoomConnect(
room: *const c_void,
url: CFStringRef,
token: CFStringRef,
callback: extern "C" fn(*mut c_void, CFStringRef) -> (),
callback: extern "C" fn(*mut c_void, CFStringRef),
callback_data: *mut c_void,
);
fn LKRoomPublishVideoTrack(
room: *const c_void,
track: *const c_void,
callback: extern "C" fn(*mut c_void, CFStringRef) -> (),
callback: extern "C" fn(*mut c_void, CFStringRef),
callback_data: *mut c_void,
);
fn LKCreateScreenShareTrackForWindow(windowId: u32) -> *const c_void;
}
pub struct Room(*const c_void);
pub struct Room {
debug_name: &'static str,
native_room: *const c_void,
_delegate: RoomDelegate,
}
impl Room {
pub fn new() -> Self {
Self(unsafe { LKRoomCreate() })
pub fn new(debug_name: &'static str) -> Arc<Self> {
Arc::new_cyclic(|weak_room| {
let delegate = RoomDelegate::new(weak_room.clone());
Self {
debug_name,
native_room: unsafe { LKRoomCreate(delegate.native_delegate) },
_delegate: delegate,
}
})
}
pub fn connect(&self, url: &str, token: &str) -> impl Future<Output = Result<()>> {
@ -47,7 +69,7 @@ impl Room {
let (did_connect, tx, rx) = Self::build_done_callback();
unsafe {
LKRoomConnect(
self.0,
self.native_room,
url.as_concrete_TypeRef(),
token.as_concrete_TypeRef(),
did_connect,
@ -61,11 +83,15 @@ impl Room {
pub fn publish_video_track(&self, track: &LocalVideoTrack) -> impl Future<Output = Result<()>> {
let (did_publish, tx, rx) = Self::build_done_callback();
unsafe {
LKRoomPublishVideoTrack(self.0, track.0, did_publish, tx);
LKRoomPublishVideoTrack(self.native_room, track.0, did_publish, tx);
}
async { rx.await.unwrap().context("error publishing video track") }
}
fn did_subscribe_to_remote_track(&self, track: RemoteVideoTrack) {
println!("{}: !!!!!!!!!!!!!!!!!!", self.debug_name);
}
fn build_done_callback() -> (
extern "C" fn(*mut c_void, CFStringRef),
*mut c_void,
@ -91,7 +117,46 @@ impl Room {
impl Drop for Room {
fn drop(&mut self) {
unsafe { LKRelease(self.0) }
unsafe { LKRelease(self.native_room) }
}
}
struct RoomDelegate {
native_delegate: *const c_void,
weak_room: *const Room,
}
impl RoomDelegate {
fn new(weak_room: Weak<Room>) -> Self {
let weak_room = Weak::into_raw(weak_room);
let native_delegate = unsafe {
LKRoomDelegateCreate(
weak_room as *const c_void,
Self::on_did_subscribe_to_remote_track,
)
};
Self {
native_delegate,
weak_room,
}
}
extern "C" fn on_did_subscribe_to_remote_track(room: *mut c_void, track: *const c_void) {
let room = unsafe { Weak::from_raw(room as *mut Room) };
let track = unsafe { RemoteVideoTrack(track) };
if let Some(room) = room.upgrade() {
room.did_subscribe_to_remote_track(track);
}
let _ = Weak::into_raw(room);
}
}
impl Drop for RoomDelegate {
fn drop(&mut self) {
unsafe {
LKRelease(self.native_delegate);
let _ = Weak::from_raw(self.weak_room);
}
}
}
@ -109,6 +174,14 @@ impl Drop for LocalVideoTrack {
}
}
pub struct RemoteVideoTrack(*const c_void);
impl Drop for RemoteVideoTrack {
fn drop(&mut self) {
unsafe { LKRelease(self.0) }
}
}
#[derive(Debug)]
pub struct WindowInfo {
pub id: u32,