1import Foundation
2import LiveKit
3import WebRTC
4
5class LKRoomDelegate: RoomDelegate {
6 var data: UnsafeRawPointer
7 var onDidSubscribeToRemoteVideoTrack: @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void
8
9 init(data: UnsafeRawPointer, onDidSubscribeToRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void) {
10 self.data = data
11 self.onDidSubscribeToRemoteVideoTrack = onDidSubscribeToRemoteVideoTrack
12 }
13
14 func room(_ room: Room, participant: RemoteParticipant, didSubscribe publication: RemoteTrackPublication, track: Track) {
15 if track.kind == .video {
16 self.onDidSubscribeToRemoteVideoTrack(self.data, Unmanaged.passRetained(track).toOpaque())
17 }
18 }
19}
20
21class LKVideoRenderer: NSObject, VideoRenderer {
22 var data: UnsafeRawPointer
23 var onFrame: @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void
24 var onDrop: @convention(c) (UnsafeRawPointer) -> Void
25 var adaptiveStreamIsEnabled: Bool = false
26 var adaptiveStreamSize: CGSize = .zero
27
28 init(data: UnsafeRawPointer, onFrame: @escaping @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void, onDrop: @escaping @convention(c) (UnsafeRawPointer) -> Void) {
29 self.data = data
30 self.onFrame = onFrame
31 self.onDrop = onDrop
32 }
33
34 deinit {
35 self.onDrop(self.data)
36 }
37
38 func setSize(_ size: CGSize) {
39 print("Called setSize", size);
40 }
41
42 func renderFrame(_ frame: RTCVideoFrame?) {
43 let buffer = frame?.buffer as? RTCCVPixelBuffer
44 if let pixelBuffer = buffer?.pixelBuffer {
45 self.onFrame(self.data, pixelBuffer)
46 }
47 }
48}
49
50@_cdecl("LKRelease")
51public func LKRelease(ptr: UnsafeRawPointer) {
52 let _ = Unmanaged<AnyObject>.fromOpaque(ptr).takeRetainedValue()
53}
54
55@_cdecl("LKRoomDelegateCreate")
56public func LKRoomDelegateCreate(data: UnsafeRawPointer, onDidSubscribeToRemoteVideoTrack: @escaping @convention(c) (UnsafeRawPointer, UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
57 let delegate = LKRoomDelegate(data: data, onDidSubscribeToRemoteVideoTrack: onDidSubscribeToRemoteVideoTrack)
58 return Unmanaged.passRetained(delegate).toOpaque()
59}
60
61@_cdecl("LKRoomCreate")
62public func LKRoomCreate(delegate: UnsafeRawPointer) -> UnsafeMutableRawPointer {
63 let delegate = Unmanaged<LKRoomDelegate>.fromOpaque(delegate).takeUnretainedValue()
64 return Unmanaged.passRetained(Room(delegate: delegate)).toOpaque()
65}
66
67@_cdecl("LKRoomConnect")
68public func LKRoomConnect(room: UnsafeRawPointer, url: CFString, token: CFString, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
69 let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
70
71 room.connect(url as String, token as String).then { _ in
72 callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
73 }.catch { error in
74 callback(callback_data, error.localizedDescription as CFString)
75 }
76}
77
78@_cdecl("LKRoomPublishVideoTrack")
79public func LKRoomPublishVideoTrack(room: UnsafeRawPointer, track: UnsafeRawPointer, callback: @escaping @convention(c) (UnsafeRawPointer, CFString?) -> Void, callback_data: UnsafeRawPointer) {
80 let room = Unmanaged<Room>.fromOpaque(room).takeUnretainedValue()
81 let track = Unmanaged<LocalVideoTrack>.fromOpaque(track).takeUnretainedValue()
82 room.localParticipant?.publishVideoTrack(track: track).then { _ in
83 callback(callback_data, UnsafeRawPointer(nil) as! CFString?)
84 }.catch { error in
85 callback(callback_data, error.localizedDescription as CFString)
86 }
87}
88
89@_cdecl("LKCreateScreenShareTrackForWindow")
90public func LKCreateScreenShareTrackForWindow(windowId: uint32) -> UnsafeMutableRawPointer {
91 let track = LocalVideoTrack.createMacOSScreenShareTrack(source: .window(id: windowId))
92 return Unmanaged.passRetained(track).toOpaque()
93}
94
95@_cdecl("LKVideoRendererCreate")
96public func LKVideoRendererCreate(data: UnsafeRawPointer, onFrame: @escaping @convention(c) (UnsafeRawPointer, CVPixelBuffer) -> Void, onDrop: @escaping @convention(c) (UnsafeRawPointer) -> Void) -> UnsafeMutableRawPointer {
97 Unmanaged.passRetained(LKVideoRenderer(data: data, onFrame: onFrame, onDrop: onDrop)).toOpaque()
98}
99
100@_cdecl("LKVideoTrackAddRenderer")
101public func LKVideoTrackAddRenderer(track: UnsafeRawPointer, renderer: UnsafeRawPointer) {
102 let track = Unmanaged<Track>.fromOpaque(track).takeUnretainedValue() as! VideoTrack
103 let renderer = Unmanaged<LKVideoRenderer>.fromOpaque(renderer).takeRetainedValue()
104 track.add(videoRenderer: renderer)
105}