Register to publishing of remote tracks
This commit is contained in:
parent
37ca5651ee
commit
645338cff8
3 changed files with 143 additions and 34 deletions
|
@ -1,5 +1,7 @@
|
||||||
mod live_kit_token;
|
mod live_kit_token;
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions,
|
actions,
|
||||||
elements::{Canvas, *},
|
elements::{Canvas, *},
|
||||||
|
@ -34,25 +36,38 @@ fn main() {
|
||||||
let live_kit_key = std::env::var("LIVE_KIT_KEY").unwrap();
|
let live_kit_key = std::env::var("LIVE_KIT_KEY").unwrap();
|
||||||
let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap();
|
let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap();
|
||||||
|
|
||||||
let token = live_kit_token::create_token(
|
let background = cx.background().clone();
|
||||||
&live_kit_key,
|
|
||||||
&live_kit_secret,
|
|
||||||
"test-room",
|
|
||||||
"test-participant",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let room = Room::new();
|
|
||||||
cx.foreground()
|
cx.foreground()
|
||||||
.spawn(async move {
|
.spawn(async move {
|
||||||
println!("connecting...");
|
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();
|
let windows = live_kit::list_windows();
|
||||||
println!("connected! {:?}", windows);
|
println!("connected! {:?}", windows);
|
||||||
|
|
||||||
let window_id = windows.iter().next().unwrap().id;
|
let window_id = windows.iter().next().unwrap().id;
|
||||||
let track = LocalVideoTrack::screen_share_for_window(window_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();
|
.detach();
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,61 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import LiveKit
|
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")
|
@_cdecl("LKRelease")
|
||||||
public func LKRelease(ptr: UnsafeRawPointer) {
|
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")
|
@_cdecl("LKRoomCreate")
|
||||||
public func LKRoomCreate() -> UnsafeMutableRawPointer {
|
public func LKRoomCreate(delegate: UnsafeRawPointer) -> UnsafeMutableRawPointer {
|
||||||
Unmanaged.passRetained(Room()).toOpaque()
|
let delegate = Unmanaged<LKRoomDelegate>.fromOpaque(delegate).takeUnretainedValue()
|
||||||
|
return Unmanaged.passRetained(Room(delegate: delegate)).toOpaque()
|
||||||
}
|
}
|
||||||
|
|
||||||
@_cdecl("LKRoomConnect")
|
@_cdecl("LKRoomConnect")
|
||||||
public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
|
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
|
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
|
}.catch { error in
|
||||||
callback(callback_data, error.localizedDescription as CFString);
|
callback(callback_data, error.localizedDescription as CFString)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@_cdecl("LKRoomPublishVideoTrack")
|
@_cdecl("LKRoomPublishVideoTrack")
|
||||||
public func LKRoomPublishVideoTrack(room: UnsafeRawPointer, track: UnsafeRawPointer, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
|
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 room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
|
||||||
let track = Unmanaged<LocalVideoTrack>.fromOpaque(track).takeUnretainedValue();
|
let track = Unmanaged<LocalVideoTrack>.fromOpaque(track).takeUnretainedValue()
|
||||||
room.localParticipant?.publishVideoTrack(track: track).then { _ in
|
room.localParticipant?.publishVideoTrack(track: track).then { _ in
|
||||||
callback(callback_data, UnsafeRawPointer(nil) as! CFString?);
|
callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
|
||||||
}.catch { error in
|
}.catch { error in
|
||||||
callback(callback_data, error.localizedDescription as CFString);
|
callback(callback_data, error.localizedDescription as CFString)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@_cdecl("LKCreateScreenShareTrackForWindow")
|
@_cdecl("LKCreateScreenShareTrackForWindow")
|
||||||
public func LKCreateScreenShareTrackForWindow(windowId: uint32) -> UnsafeMutableRawPointer {
|
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()
|
return Unmanaged.passRetained(track).toOpaque()
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,34 +11,56 @@ use core_graphics::window::{
|
||||||
kCGWindowNumber, kCGWindowOwnerName, kCGWindowOwnerPID, CGWindowListCopyWindowInfo,
|
kCGWindowNumber, kCGWindowOwnerName, kCGWindowOwnerPID, CGWindowListCopyWindowInfo,
|
||||||
};
|
};
|
||||||
use futures::{channel::oneshot, Future};
|
use futures::{channel::oneshot, Future};
|
||||||
use std::ffi::c_void;
|
use std::{
|
||||||
|
ffi::c_void,
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn LKRelease(object: *const c_void);
|
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(
|
fn LKRoomConnect(
|
||||||
room: *const c_void,
|
room: *const c_void,
|
||||||
url: CFStringRef,
|
url: CFStringRef,
|
||||||
token: CFStringRef,
|
token: CFStringRef,
|
||||||
callback: extern "C" fn(*mut c_void, CFStringRef) -> (),
|
callback: extern "C" fn(*mut c_void, CFStringRef),
|
||||||
callback_data: *mut c_void,
|
callback_data: *mut c_void,
|
||||||
);
|
);
|
||||||
fn LKRoomPublishVideoTrack(
|
fn LKRoomPublishVideoTrack(
|
||||||
room: *const c_void,
|
room: *const c_void,
|
||||||
track: *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,
|
callback_data: *mut c_void,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn LKCreateScreenShareTrackForWindow(windowId: u32) -> *const 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 {
|
impl Room {
|
||||||
pub fn new() -> Self {
|
pub fn new(debug_name: &'static str) -> Arc<Self> {
|
||||||
Self(unsafe { LKRoomCreate() })
|
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<()>> {
|
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();
|
let (did_connect, tx, rx) = Self::build_done_callback();
|
||||||
unsafe {
|
unsafe {
|
||||||
LKRoomConnect(
|
LKRoomConnect(
|
||||||
self.0,
|
self.native_room,
|
||||||
url.as_concrete_TypeRef(),
|
url.as_concrete_TypeRef(),
|
||||||
token.as_concrete_TypeRef(),
|
token.as_concrete_TypeRef(),
|
||||||
did_connect,
|
did_connect,
|
||||||
|
@ -61,11 +83,15 @@ impl Room {
|
||||||
pub fn publish_video_track(&self, track: &LocalVideoTrack) -> impl Future<Output = Result<()>> {
|
pub fn publish_video_track(&self, track: &LocalVideoTrack) -> impl Future<Output = Result<()>> {
|
||||||
let (did_publish, tx, rx) = Self::build_done_callback();
|
let (did_publish, tx, rx) = Self::build_done_callback();
|
||||||
unsafe {
|
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") }
|
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() -> (
|
fn build_done_callback() -> (
|
||||||
extern "C" fn(*mut c_void, CFStringRef),
|
extern "C" fn(*mut c_void, CFStringRef),
|
||||||
*mut c_void,
|
*mut c_void,
|
||||||
|
@ -91,7 +117,46 @@ impl Room {
|
||||||
|
|
||||||
impl Drop for Room {
|
impl Drop for Room {
|
||||||
fn drop(&mut self) {
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct WindowInfo {
|
pub struct WindowInfo {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue