WIP: Start on live_kit crate that uses a C-based bridge

This commit is contained in:
Nathan Sobo 2022-09-02 12:56:38 -06:00 committed by Antonio Scandurra
parent 52f32b50b2
commit 4bcc008cbf
12 changed files with 254 additions and 88 deletions

11
Cargo.lock generated
View file

@ -765,13 +765,12 @@ dependencies = [
"foreign-types",
"futures",
"gpui",
"live_kit",
"log",
"media",
"objc",
"parking_lot 0.11.2",
"postage",
"serde",
"serde_json",
"simplelog",
]
@ -2918,6 +2917,14 @@ dependencies = [
"rand_chacha 0.3.1",
]
[[package]]
name = "live_kit"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "lock_api"
version = "0.4.7"

View file

@ -6,6 +6,7 @@ description = "An example of screen capture"
[dependencies]
gpui = { path = "../gpui" }
live_kit = { path = "../live_kit" }
media = { path = "../media" }
anyhow = "1.0.38"
@ -25,5 +26,3 @@ simplelog = "0.9"
[build-dependencies]
bindgen = "0.59.2"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = { version = "1.0", features = ["preserve_order"] }

View file

@ -1,68 +1,15 @@
use serde::Deserialize;
use std::{env, path::PathBuf, process::Command};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SwiftTargetInfo {
pub triple: String,
pub unversioned_triple: String,
pub module_triple: String,
pub swift_runtime_compatibility_version: String,
#[serde(rename = "librariesRequireRPath")]
pub libraries_require_rpath: bool,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SwiftPaths {
pub runtime_library_paths: Vec<String>,
pub runtime_library_import_paths: Vec<String>,
pub runtime_resource_path: String,
}
#[derive(Debug, Deserialize)]
pub struct SwiftTarget {
pub target: SwiftTargetInfo,
pub paths: SwiftPaths,
}
const MACOS_TARGET_VERSION: &str = "12";
pub fn link_swift_libs() {
let mut arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if arch == "aarch64" {
arch = "arm64".into();
}
let target = format!("{}-apple-macosx{}", arch, MACOS_TARGET_VERSION);
let swift_target_info_str = Command::new("swift")
.args(&["-target", &target, "-print-target-info"])
.output()
.unwrap()
.stdout;
let swift_target_info: SwiftTarget = serde_json::from_slice(&swift_target_info_str).unwrap();
if swift_target_info.target.libraries_require_rpath {
panic!("Libraries require RPath! Change minimum MacOS value to fix.")
}
swift_target_info
.paths
.runtime_library_paths
.iter()
.for_each(|path| {
println!("cargo:rustc-link-search=native={}", path);
});
}
fn main() {
link_swift_libs();
println!("cargo:rerun-if-changed=/Users/as-cii/Library/Developer/Xcode/DerivedData/LiveKitObjC-ftgpxknhsgkrocbhhgjkyyvkgkbj/Build/Products/Debug/libLiveKitObjC.a");
println!("cargo:rustc-link-search=native=/Users/as-cii/Library/Developer/Xcode/DerivedData/LiveKitObjC-ftgpxknhsgkrocbhhgjkyyvkgkbj/Build/Products/libs");
println!("cargo:rustc-link-search=framework=/Users/as-cii/Library/Developer/Xcode/DerivedData/LiveKitObjC-ftgpxknhsgkrocbhhgjkyyvkgkbj/Build/Products/frameworks");
println!("cargo:rustc-link-lib=static=LiveKitObjC");
println!(
"cargo:rustc-link-search=framework={}",
"crates/live_kit/LiveKitBridge/.build/arm64-apple-macosx/debug"
);
// Find frameworks as a sibling of the executable at runtime
println!("cargo:rustc-link-arg=-Wl,-rpath,@executable_path");
println!("cargo:rustc-link-lib=framework=ScreenCaptureKit");
println!("cargo:rustc-link-lib=framework=WebRTC");
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=12.3");
let sdk_path = String::from_utf8(

View file

@ -22,6 +22,7 @@ use gpui::{
platform::current::Surface,
Menu, MenuItem, ViewContext,
};
use live_kit::Room;
use log::LevelFilter;
use media::{
core_media::{
@ -47,29 +48,6 @@ const NSUTF8StringEncoding: NSUInteger = 4;
actions!(capture, [Quit]);
extern "C" {
fn LKRoomCreate() -> *const c_void;
fn LKRoomDestroy(ptr: *const c_void);
}
struct Room {
native_room: *const c_void,
}
impl Room {
pub fn new() -> Self {
Self {
native_room: unsafe { LKRoomCreate() },
}
}
}
impl Drop for Room {
fn drop(&mut self) {
unsafe { LKRoomDestroy(self.native_room) }
}
}
fn main() {
println!("Creating room...");
let room = Room::new();

View file

@ -0,0 +1,15 @@
[package]
name = "live_kit"
version = "0.1.0"
edition = "2021"
description = "Bindings to LiveKit Swift client SDK"
[lib]
path = "src/live_kit.rs"
doctest = false
[dependencies]
[build-dependencies]
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = { version = "1.0", features = ["preserve_order"] }

View file

@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

View file

@ -0,0 +1,50 @@
{
"pins" : [
{
"identity" : "client-sdk-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/livekit/client-sdk-swift.git",
"state" : {
"revision" : "7e7decf3a09de4a169dfc0445a14d9fd2d8db58d",
"version" : "1.0.4"
}
},
{
"identity" : "promises",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/promises.git",
"state" : {
"revision" : "3e4e743631e86c8c70dbc6efdc7beaa6e90fd3bb",
"version" : "2.1.1"
}
},
{
"identity" : "specs",
"kind" : "remoteSourceControl",
"location" : "https://github.com/webrtc-sdk/Specs.git",
"state" : {
"revision" : "5225f2de4b6d0098803b3a0e55b255a41f293dad",
"version" : "104.5112.2"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "6fe203dc33195667ce1759bf0182975e4653ba1c",
"version" : "1.4.4"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "b8230909dedc640294d7324d37f4c91ad3dcf177",
"version" : "1.20.1"
}
}
],
"version" : 2
}

View file

@ -0,0 +1,27 @@
// swift-tools-version: 5.6
import PackageDescription
let package = Package(
name: "LiveKitBridge",
platforms: [
.macOS(.v10_15)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "LiveKitBridge",
type: .static,
targets: ["LiveKitBridge"]),
],
dependencies: [
.package(url: "https://github.com/livekit/client-sdk-swift.git", from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "LiveKitBridge",
dependencies: [.product(name: "LiveKit", package: "client-sdk-swift")]),
]
)

View file

@ -0,0 +1,3 @@
# LiveKitBridge
A description of this package.

View file

@ -0,0 +1,12 @@
import Foundation
import LiveKit
@_cdecl("LKRoomCreate")
public func LKRoomCreate() -> UnsafeMutableRawPointer {
Unmanaged.passRetained(Room()).toOpaque()
}
@_cdecl("LKRoomDestroy")
public func LKRoomDestroy(ptr: UnsafeRawPointer) {
let _ = Unmanaged<Room>.fromOpaque(ptr).takeRetainedValue();
}

95
crates/live_kit/build.rs Normal file
View file

@ -0,0 +1,95 @@
use serde::Deserialize;
use std::{env, path::PathBuf, process::Command};
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SwiftTargetInfo {
pub triple: String,
pub unversioned_triple: String,
pub module_triple: String,
pub swift_runtime_compatibility_version: String,
#[serde(rename = "librariesRequireRPath")]
pub libraries_require_rpath: bool,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SwiftPaths {
pub runtime_library_paths: Vec<String>,
pub runtime_library_import_paths: Vec<String>,
pub runtime_resource_path: String,
}
#[derive(Debug, Deserialize)]
pub struct SwiftTarget {
pub target: SwiftTargetInfo,
pub paths: SwiftPaths,
}
const MACOS_TARGET_VERSION: &str = "12";
fn main() {
build_bridge();
link_swift_stdlib();
}
fn build_bridge() {
let profile = env::var("PROFILE").unwrap();
let package_name = "LiveKitBridge";
let package_root = env::current_dir().unwrap().join(package_name);
if !Command::new("swift")
.args(&["build", "-c", &profile])
.current_dir(&package_root)
.status()
.unwrap()
.success()
{
panic!(
"Failed to compile swift package in {}",
package_root.display()
);
}
let swift_target_info = get_swift_target();
let swift_out_dir_path = format!(
"{}/.build/{}/{}",
package_root.display(),
swift_target_info.target.unversioned_triple,
profile
);
println!("cargo:rustc-link-search=native={}", swift_out_dir_path);
println!(
"cargo:rustc-link-search=framework={}",
"/Users/nathan/src/zed/crates/live_kit/frameworks"
);
println!("cargo:rustc-link-lib=static={}", package_name);
println!("cargo:rustc-link-lib=framework=WebRTC");
}
fn link_swift_stdlib() {
let target = get_swift_target();
if target.target.libraries_require_rpath {
panic!("Libraries require RPath! Change minimum MacOS value to fix.")
}
target.paths.runtime_library_paths.iter().for_each(|path| {
println!("cargo:rustc-link-search=native={}", path);
});
}
fn get_swift_target() -> SwiftTarget {
let mut arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if arch == "aarch64" {
arch = "arm64".into();
}
let target = format!("{}-apple-macosx{}", arch, MACOS_TARGET_VERSION);
let swift_target_info_str = Command::new("swift")
.args(&["-target", &target, "-print-target-info"])
.output()
.unwrap()
.stdout;
serde_json::from_slice(&swift_target_info_str).unwrap()
}

View file

@ -0,0 +1,24 @@
use std::ffi::c_void;
extern "C" {
fn LKRoomCreate() -> *const c_void;
fn LKRoomDestroy(ptr: *const c_void);
}
pub struct Room {
native_room: *const c_void,
}
impl Room {
pub fn new() -> Self {
Self {
native_room: unsafe { LKRoomCreate() },
}
}
}
impl Drop for Room {
fn drop(&mut self) {
unsafe { LKRoomDestroy(self.native_room) }
}
}