iOS screen share (#133)
This commit is contained in:
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Atomic.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Maksym Shcheglov.
|
||||||
|
// https://www.onswiftwings.com/posts/atomic-property-wrapper/
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct Atomic<Value> {
|
||||||
|
|
||||||
|
private var value: Value
|
||||||
|
private let lock = NSLock()
|
||||||
|
|
||||||
|
init(wrappedValue value: Value) {
|
||||||
|
self.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
var wrappedValue: Value {
|
||||||
|
get { load() }
|
||||||
|
set { store(newValue: newValue) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func load() -> Value {
|
||||||
|
lock.lock()
|
||||||
|
defer { lock.unlock() }
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func store(newValue: Value) {
|
||||||
|
lock.lock()
|
||||||
|
defer { lock.unlock() }
|
||||||
|
value = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// DarwinNotificationCenter.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 23/03/2021.
|
||||||
|
// Copyright © 2021 8x8, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum DarwinNotification: String {
|
||||||
|
case broadcastStarted = "iOS_BroadcastStarted"
|
||||||
|
case broadcastStopped = "iOS_BroadcastStopped"
|
||||||
|
}
|
||||||
|
|
||||||
|
class DarwinNotificationCenter {
|
||||||
|
|
||||||
|
static let shared = DarwinNotificationCenter()
|
||||||
|
|
||||||
|
private let notificationCenter: CFNotificationCenter
|
||||||
|
|
||||||
|
init() {
|
||||||
|
notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
func postNotification(_ name: DarwinNotification) {
|
||||||
|
CFNotificationCenterPostNotification(notificationCenter, CFNotificationName(rawValue: name.rawValue as CFString), nil, nil, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.broadcast-services-upload</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).SampleHandler</string>
|
||||||
|
<key>RPBroadcastProcessMode</key>
|
||||||
|
<string>RPBroadcastProcessModeSampleBuffer</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.io.livekit.example.flutter</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
//
|
||||||
|
// SampleHandler.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 04.06.2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import ReplayKit
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
let broadcastLogger = OSLog(subsystem: "io.livekit.example.flutter", category: "Broadcast")
|
||||||
|
private enum Constants {
|
||||||
|
// the App Group ID value that the app and the broadcast extension targets are setup with. It differs for each app.
|
||||||
|
static let appGroupIdentifier = "group.io.livekit.example.flutter"
|
||||||
|
}
|
||||||
|
|
||||||
|
class SampleHandler: RPBroadcastSampleHandler {
|
||||||
|
|
||||||
|
private var clientConnection: SocketConnection?
|
||||||
|
private var uploader: SampleUploader?
|
||||||
|
|
||||||
|
private var frameCount: Int = 0
|
||||||
|
|
||||||
|
var socketFilePath: String {
|
||||||
|
let sharedContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupIdentifier)
|
||||||
|
return sharedContainer?.appendingPathComponent("rtc_SSFD").path ?? ""
|
||||||
|
}
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
if let connection = SocketConnection(filePath: socketFilePath) {
|
||||||
|
clientConnection = connection
|
||||||
|
setupConnection()
|
||||||
|
|
||||||
|
uploader = SampleUploader(connection: connection)
|
||||||
|
}
|
||||||
|
os_log(.debug, log: broadcastLogger, "%{public}s", socketFilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) {
|
||||||
|
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
|
||||||
|
frameCount = 0
|
||||||
|
|
||||||
|
DarwinNotificationCenter.shared.postNotification(.broadcastStarted)
|
||||||
|
openConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastPaused() {
|
||||||
|
// User has requested to pause the broadcast. Samples will stop being delivered.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastResumed() {
|
||||||
|
// User has requested to resume the broadcast. Samples delivery will resume.
|
||||||
|
}
|
||||||
|
|
||||||
|
override func broadcastFinished() {
|
||||||
|
// User has requested to finish the broadcast.
|
||||||
|
DarwinNotificationCenter.shared.postNotification(.broadcastStopped)
|
||||||
|
clientConnection?.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
|
||||||
|
switch sampleBufferType {
|
||||||
|
case RPSampleBufferType.video:
|
||||||
|
uploader?.send(sample: sampleBuffer)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SampleHandler {
|
||||||
|
|
||||||
|
func setupConnection() {
|
||||||
|
clientConnection?.didClose = { [weak self] error in
|
||||||
|
os_log(.debug, log: broadcastLogger, "client connection did close \(String(describing: error))")
|
||||||
|
|
||||||
|
if let error = error {
|
||||||
|
self?.finishBroadcastWithError(error)
|
||||||
|
} else {
|
||||||
|
// the displayed failure message is more user friendly when using NSError instead of Error
|
||||||
|
let JMScreenSharingStopped = 10001
|
||||||
|
let customError = NSError(domain: RPRecordingErrorDomain, code: JMScreenSharingStopped, userInfo: [NSLocalizedDescriptionKey: "Screen sharing stopped"])
|
||||||
|
self?.finishBroadcastWithError(customError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func openConnection() {
|
||||||
|
let queue = DispatchQueue(label: "broadcast.connectTimer")
|
||||||
|
let timer = DispatchSource.makeTimerSource(queue: queue)
|
||||||
|
timer.schedule(deadline: .now(), repeating: .milliseconds(100), leeway: .milliseconds(500))
|
||||||
|
timer.setEventHandler { [weak self] in
|
||||||
|
guard self?.clientConnection?.open() == true else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
//
|
||||||
|
// SampleUploader.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 22/03/2021.
|
||||||
|
// Copyright © 2021 8x8, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ReplayKit
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
private enum Constants {
|
||||||
|
static let bufferMaxLength = 10240
|
||||||
|
}
|
||||||
|
|
||||||
|
class SampleUploader {
|
||||||
|
|
||||||
|
private static var imageContext = CIContext(options: nil)
|
||||||
|
|
||||||
|
@Atomic private var isReady = false
|
||||||
|
private var connection: SocketConnection
|
||||||
|
|
||||||
|
private var dataToSend: Data?
|
||||||
|
private var byteIndex = 0
|
||||||
|
|
||||||
|
private let serialQueue: DispatchQueue
|
||||||
|
|
||||||
|
init(connection: SocketConnection) {
|
||||||
|
self.connection = connection
|
||||||
|
self.serialQueue = DispatchQueue(label: "org.jitsi.meet.broadcast.sampleUploader")
|
||||||
|
|
||||||
|
setupConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult func send(sample buffer: CMSampleBuffer) -> Bool {
|
||||||
|
guard isReady else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
isReady = false
|
||||||
|
|
||||||
|
dataToSend = prepare(sample: buffer)
|
||||||
|
byteIndex = 0
|
||||||
|
|
||||||
|
serialQueue.async { [weak self] in
|
||||||
|
self?.sendDataChunk()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SampleUploader {
|
||||||
|
|
||||||
|
func setupConnection() {
|
||||||
|
connection.didOpen = { [weak self] in
|
||||||
|
self?.isReady = true
|
||||||
|
}
|
||||||
|
connection.streamHasSpaceAvailable = { [weak self] in
|
||||||
|
self?.serialQueue.async {
|
||||||
|
if let success = self?.sendDataChunk() {
|
||||||
|
self?.isReady = !success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult func sendDataChunk() -> Bool {
|
||||||
|
guard let dataToSend = dataToSend else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytesLeft = dataToSend.count - byteIndex
|
||||||
|
var length = bytesLeft > Constants.bufferMaxLength ? Constants.bufferMaxLength : bytesLeft
|
||||||
|
|
||||||
|
length = dataToSend[byteIndex..<(byteIndex + length)].withUnsafeBytes {
|
||||||
|
guard let ptr = $0.bindMemory(to: UInt8.self).baseAddress else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection.writeToStream(buffer: ptr, maxLength: length)
|
||||||
|
}
|
||||||
|
|
||||||
|
if length > 0 {
|
||||||
|
byteIndex += length
|
||||||
|
bytesLeft -= length
|
||||||
|
|
||||||
|
if bytesLeft == 0 {
|
||||||
|
self.dataToSend = nil
|
||||||
|
byteIndex = 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "writeBufferToStream failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepare(sample buffer: CMSampleBuffer) -> Data? {
|
||||||
|
guard let imageBuffer = CMSampleBufferGetImageBuffer(buffer) else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "image buffer not available")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
CVPixelBufferLockBaseAddress(imageBuffer, .readOnly)
|
||||||
|
|
||||||
|
let scaleFactor = 1.0
|
||||||
|
let width = CVPixelBufferGetWidth(imageBuffer)/Int(scaleFactor)
|
||||||
|
let height = CVPixelBufferGetHeight(imageBuffer)/Int(scaleFactor)
|
||||||
|
let orientation = CMGetAttachment(buffer, key: RPVideoSampleOrientationKey as CFString, attachmentModeOut: nil)?.uintValue ?? 0
|
||||||
|
|
||||||
|
let scaleTransform = CGAffineTransform(scaleX: CGFloat(1.0/scaleFactor), y: CGFloat(1.0/scaleFactor))
|
||||||
|
let bufferData = self.jpegData(from: imageBuffer, scale: scaleTransform)
|
||||||
|
|
||||||
|
CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly)
|
||||||
|
|
||||||
|
guard let messageData = bufferData else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "corrupted image buffer")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let httpResponse = CFHTTPMessageCreateResponse(nil, 200, nil, kCFHTTPVersion1_1).takeRetainedValue()
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Content-Length" as CFString, String(messageData.count) as CFString)
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Width" as CFString, String(width) as CFString)
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Height" as CFString, String(height) as CFString)
|
||||||
|
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Orientation" as CFString, String(orientation) as CFString)
|
||||||
|
|
||||||
|
CFHTTPMessageSetBody(httpResponse, messageData as CFData)
|
||||||
|
|
||||||
|
let serializedMessage = CFHTTPMessageCopySerializedMessage(httpResponse)?.takeRetainedValue() as Data?
|
||||||
|
|
||||||
|
return serializedMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func jpegData(from buffer: CVPixelBuffer, scale scaleTransform: CGAffineTransform) -> Data? {
|
||||||
|
let image = CIImage(cvPixelBuffer: buffer).transformed(by: scaleTransform)
|
||||||
|
|
||||||
|
guard let colorSpace = image.colorSpace else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let options: [CIImageRepresentationOption: Float] = [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: 1.0]
|
||||||
|
|
||||||
|
return SampleUploader.imageContext.jpegRepresentation(of: image, colorSpace: colorSpace, options: options)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
//
|
||||||
|
// SocketConnection.swift
|
||||||
|
// Broadcast Extension
|
||||||
|
//
|
||||||
|
// Created by Alex-Dan Bumbu on 22/03/2021.
|
||||||
|
// Copyright © 2021 Atlassian Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import OSLog
|
||||||
|
|
||||||
|
class SocketConnection: NSObject {
|
||||||
|
var didOpen: (() -> Void)?
|
||||||
|
var didClose: ((Error?) -> Void)?
|
||||||
|
var streamHasSpaceAvailable: (() -> Void)?
|
||||||
|
|
||||||
|
private let filePath: String
|
||||||
|
private var socketHandle: Int32 = -1
|
||||||
|
private var address: sockaddr_un?
|
||||||
|
|
||||||
|
private var inputStream: InputStream?
|
||||||
|
private var outputStream: OutputStream?
|
||||||
|
|
||||||
|
private var networkQueue: DispatchQueue?
|
||||||
|
private var shouldKeepRunning = false
|
||||||
|
|
||||||
|
init?(filePath path: String) {
|
||||||
|
filePath = path
|
||||||
|
socketHandle = Darwin.socket(AF_UNIX, SOCK_STREAM, 0)
|
||||||
|
|
||||||
|
guard socketHandle != -1 else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: create socket")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func open() -> Bool {
|
||||||
|
os_log(.debug, log: broadcastLogger, "open socket connection")
|
||||||
|
|
||||||
|
guard FileManager.default.fileExists(atPath: filePath) else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: socket file missing")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
guard setupAddress() == true else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
guard connectSocket() == true else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
setupStreams()
|
||||||
|
|
||||||
|
inputStream?.open()
|
||||||
|
outputStream?.open()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func close() {
|
||||||
|
unscheduleStreams()
|
||||||
|
|
||||||
|
inputStream?.delegate = nil
|
||||||
|
outputStream?.delegate = nil
|
||||||
|
|
||||||
|
inputStream?.close()
|
||||||
|
outputStream?.close()
|
||||||
|
|
||||||
|
inputStream = nil
|
||||||
|
outputStream = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeToStream(buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int {
|
||||||
|
outputStream?.write(buffer, maxLength: length) ?? 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SocketConnection: StreamDelegate {
|
||||||
|
|
||||||
|
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
|
||||||
|
switch eventCode {
|
||||||
|
case .openCompleted:
|
||||||
|
os_log(.debug, log: broadcastLogger, "client stream open completed")
|
||||||
|
if aStream == outputStream {
|
||||||
|
didOpen?()
|
||||||
|
}
|
||||||
|
case .hasBytesAvailable:
|
||||||
|
if aStream == inputStream {
|
||||||
|
var buffer: UInt8 = 0
|
||||||
|
let numberOfBytesRead = inputStream?.read(&buffer, maxLength: 1)
|
||||||
|
if numberOfBytesRead == 0 && aStream.streamStatus == .atEnd {
|
||||||
|
os_log(.debug, log: broadcastLogger, "server socket closed")
|
||||||
|
close()
|
||||||
|
notifyDidClose(error: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .hasSpaceAvailable:
|
||||||
|
if aStream == outputStream {
|
||||||
|
streamHasSpaceAvailable?()
|
||||||
|
}
|
||||||
|
case .errorOccurred:
|
||||||
|
os_log(.debug, log: broadcastLogger, "client stream error occured: \(String(describing: aStream.streamError))")
|
||||||
|
close()
|
||||||
|
notifyDidClose(error: aStream.streamError)
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension SocketConnection {
|
||||||
|
|
||||||
|
func setupAddress() -> Bool {
|
||||||
|
var addr = sockaddr_un()
|
||||||
|
guard filePath.count < MemoryLayout.size(ofValue: addr.sun_path) else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: fd path is too long")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = withUnsafeMutablePointer(to: &addr.sun_path.0) { ptr in
|
||||||
|
filePath.withCString {
|
||||||
|
strncpy(ptr, $0, filePath.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address = addr
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func connectSocket() -> Bool {
|
||||||
|
guard var addr = address else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = withUnsafePointer(to: &addr) { ptr in
|
||||||
|
ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) {
|
||||||
|
Darwin.connect(socketHandle, $0, socklen_t(MemoryLayout<sockaddr_un>.size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard status == noErr else {
|
||||||
|
os_log(.debug, log: broadcastLogger, "failure: \(status)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupStreams() {
|
||||||
|
var readStream: Unmanaged<CFReadStream>?
|
||||||
|
var writeStream: Unmanaged<CFWriteStream>?
|
||||||
|
|
||||||
|
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketHandle, &readStream, &writeStream)
|
||||||
|
|
||||||
|
inputStream = readStream?.takeRetainedValue()
|
||||||
|
inputStream?.delegate = self
|
||||||
|
inputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
|
||||||
|
|
||||||
|
outputStream = writeStream?.takeRetainedValue()
|
||||||
|
outputStream?.delegate = self
|
||||||
|
outputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
|
||||||
|
|
||||||
|
scheduleStreams()
|
||||||
|
}
|
||||||
|
|
||||||
|
func scheduleStreams() {
|
||||||
|
shouldKeepRunning = true
|
||||||
|
|
||||||
|
networkQueue = DispatchQueue.global(qos: .userInitiated)
|
||||||
|
networkQueue?.async { [weak self] in
|
||||||
|
self?.inputStream?.schedule(in: .current, forMode: .common)
|
||||||
|
self?.outputStream?.schedule(in: .current, forMode: .common)
|
||||||
|
RunLoop.current.run()
|
||||||
|
|
||||||
|
var isRunning = false
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
isRunning = self?.shouldKeepRunning ?? false && RunLoop.current.run(mode: .default, before: .distantFuture)
|
||||||
|
} while (isRunning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unscheduleStreams() {
|
||||||
|
networkQueue?.sync { [weak self] in
|
||||||
|
self?.inputStream?.remove(from: .current, forMode: .common)
|
||||||
|
self?.outputStream?.remove(from: .current, forMode: .common)
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldKeepRunning = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyDidClose(error: Error?) {
|
||||||
|
if didClose != nil {
|
||||||
|
didClose?(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ PODS:
|
|||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_webrtc (0.7.1):
|
- flutter_webrtc (0.8.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (= 97.4692.05)
|
- WebRTC-SDK (= 97.4692.05)
|
||||||
- livekit_client (1.0.0):
|
- livekit_client (1.0.0):
|
||||||
@@ -43,7 +43,7 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
|
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
|
||||||
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
|
||||||
flutter_webrtc: c4d09b864e7a8e93ad931bb84eed0ceb1ed51444
|
flutter_webrtc: 1062ea68c08f530ad3d97f743729dd390d8cbf7b
|
||||||
livekit_client: bfe6ba8be81816356cf2b06483179227c832a986
|
livekit_client: bfe6ba8be81816356cf2b06483179227c832a986
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
||||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
||||||
|
|||||||
@@ -14,8 +14,25 @@
|
|||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
D7FECD282860997500D04D1C /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7FECD272860997400D04D1C /* ReplayKit.framework */; };
|
||||||
|
D7FECD2F2860997500D04D1C /* LiveKit Broadcast Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D7FECD262860997400D04D1C /* LiveKit Broadcast Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
D7FECD3B286099EE00D04D1C /* SocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FECD36286099EE00D04D1C /* SocketConnection.swift */; };
|
||||||
|
D7FECD3C286099EE00D04D1C /* SampleHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FECD37286099EE00D04D1C /* SampleHandler.swift */; };
|
||||||
|
D7FECD3D286099EE00D04D1C /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FECD38286099EE00D04D1C /* Atomic.swift */; };
|
||||||
|
D7FECD3E286099EE00D04D1C /* DarwinNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FECD39286099EE00D04D1C /* DarwinNotificationCenter.swift */; };
|
||||||
|
D7FECD3F286099EE00D04D1C /* SampleUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FECD3A286099EE00D04D1C /* SampleUploader.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
D7FECD2D2860997500D04D1C /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = D7FECD252860997400D04D1C;
|
||||||
|
remoteInfo = "LiveKit Broadcast Extension";
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
@@ -27,6 +44,17 @@
|
|||||||
name = "Embed Frameworks";
|
name = "Embed Frameworks";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D7FECD302860997500D04D1C /* Embed App Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
D7FECD2F2860997500D04D1C /* LiveKit Broadcast Extension.appex in Embed App Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed App Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@@ -45,6 +73,16 @@
|
|||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
D7FECD262860997400D04D1C /* LiveKit Broadcast Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "LiveKit Broadcast Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
D7FECD272860997400D04D1C /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
||||||
|
D7FECD2C2860997500D04D1C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
D7FECD352860998A00D04D1C /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
|
D7FECD36286099EE00D04D1C /* SocketConnection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketConnection.swift; sourceTree = "<group>"; };
|
||||||
|
D7FECD37286099EE00D04D1C /* SampleHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleHandler.swift; sourceTree = "<group>"; };
|
||||||
|
D7FECD38286099EE00D04D1C /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
|
||||||
|
D7FECD39286099EE00D04D1C /* DarwinNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarwinNotificationCenter.swift; sourceTree = "<group>"; };
|
||||||
|
D7FECD3A286099EE00D04D1C /* SampleUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleUploader.swift; sourceTree = "<group>"; };
|
||||||
|
D7FECD402860A32000D04D1C /* LiveKit Broadcast Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "LiveKit Broadcast Extension.entitlements"; sourceTree = "<group>"; };
|
||||||
D921B8649EE4CE6E91156304 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
D921B8649EE4CE6E91156304 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
ED81679F29CEB979FBD03BCE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
ED81679F29CEB979FBD03BCE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
@@ -58,6 +96,14 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D7FECD232860997400D04D1C /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D7FECD282860997500D04D1C /* ReplayKit.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
@@ -65,6 +111,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
09B43753FB1E220F505A0AA8 /* Pods_Runner.framework */,
|
09B43753FB1E220F505A0AA8 /* Pods_Runner.framework */,
|
||||||
|
D7FECD272860997400D04D1C /* ReplayKit.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -85,6 +132,7 @@
|
|||||||
children = (
|
children = (
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
D7FECD292860997500D04D1C /* LiveKit Broadcast Extension */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
E484AC95536901EEBD680DBE /* Pods */,
|
E484AC95536901EEBD680DBE /* Pods */,
|
||||||
3D7376885FAAA7D47D78511C /* Frameworks */,
|
3D7376885FAAA7D47D78511C /* Frameworks */,
|
||||||
@@ -95,6 +143,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
D7FECD262860997400D04D1C /* LiveKit Broadcast Extension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -102,6 +151,7 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D7FECD352860998A00D04D1C /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
@@ -114,6 +164,20 @@
|
|||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D7FECD292860997500D04D1C /* LiveKit Broadcast Extension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D7FECD402860A32000D04D1C /* LiveKit Broadcast Extension.entitlements */,
|
||||||
|
D7FECD38286099EE00D04D1C /* Atomic.swift */,
|
||||||
|
D7FECD39286099EE00D04D1C /* DarwinNotificationCenter.swift */,
|
||||||
|
D7FECD37286099EE00D04D1C /* SampleHandler.swift */,
|
||||||
|
D7FECD3A286099EE00D04D1C /* SampleUploader.swift */,
|
||||||
|
D7FECD36286099EE00D04D1C /* SocketConnection.swift */,
|
||||||
|
D7FECD2C2860997500D04D1C /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = "LiveKit Broadcast Extension";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E484AC95536901EEBD680DBE /* Pods */ = {
|
E484AC95536901EEBD680DBE /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -139,22 +203,42 @@
|
|||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
D9316257C44ACC699FF042FD /* [CP] Embed Pods Frameworks */,
|
D9316257C44ACC699FF042FD /* [CP] Embed Pods Frameworks */,
|
||||||
|
D7FECD302860997500D04D1C /* Embed App Extensions */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
D7FECD2E2860997500D04D1C /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
|
D7FECD252860997400D04D1C /* LiveKit Broadcast Extension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = D7FECD342860997500D04D1C /* Build configuration list for PBXNativeTarget "LiveKit Broadcast Extension" */;
|
||||||
|
buildPhases = (
|
||||||
|
D7FECD222860997400D04D1C /* Sources */,
|
||||||
|
D7FECD232860997400D04D1C /* Frameworks */,
|
||||||
|
D7FECD242860997400D04D1C /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = "LiveKit Broadcast Extension";
|
||||||
|
productName = "LiveKit Broadcast Extension";
|
||||||
|
productReference = D7FECD262860997400D04D1C /* LiveKit Broadcast Extension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
|
LastSwiftUpdateCheck = 1340;
|
||||||
LastUpgradeCheck = 1300;
|
LastUpgradeCheck = 1300;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
@@ -162,6 +246,10 @@
|
|||||||
CreatedOnToolsVersion = 7.3.1;
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
LastSwiftMigration = 1100;
|
LastSwiftMigration = 1100;
|
||||||
};
|
};
|
||||||
|
D7FECD252860997400D04D1C = {
|
||||||
|
CreatedOnToolsVersion = 13.4.1;
|
||||||
|
LastSwiftMigration = 1340;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
@@ -178,6 +266,7 @@
|
|||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
|
D7FECD252860997400D04D1C /* LiveKit Broadcast Extension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -194,6 +283,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D7FECD242860997400D04D1C /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
@@ -276,8 +372,28 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D7FECD222860997400D04D1C /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D7FECD3C286099EE00D04D1C /* SampleHandler.swift in Sources */,
|
||||||
|
D7FECD3D286099EE00D04D1C /* Atomic.swift in Sources */,
|
||||||
|
D7FECD3E286099EE00D04D1C /* DarwinNotificationCenter.swift in Sources */,
|
||||||
|
D7FECD3F286099EE00D04D1C /* SampleUploader.swift in Sources */,
|
||||||
|
D7FECD3B286099EE00D04D1C /* SocketConnection.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
D7FECD2E2860997500D04D1C /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = D7FECD252860997400D04D1C /* LiveKit Broadcast Extension */;
|
||||||
|
targetProxy = D7FECD2D2860997500D04D1C /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
@@ -353,19 +469,22 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-LiveKit";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-LiveKit";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = J48VV6BZV9;
|
DEVELOPMENT_TEAM = 76TVFCUKK7;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = io.livekit.example;
|
PRODUCT_BUNDLE_IDENTIFIER = io.livekit.example.flutter;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -488,19 +607,22 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-LiveKit";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-LiveKit";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = J48VV6BZV9;
|
DEVELOPMENT_TEAM = 76TVFCUKK7;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = io.livekit.example;
|
PRODUCT_BUNDLE_IDENTIFIER = io.livekit.example.flutter;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -514,19 +636,22 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-LiveKit";
|
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-LiveKit";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
DEVELOPMENT_TEAM = J48VV6BZV9;
|
DEVELOPMENT_TEAM = 76TVFCUKK7;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = io.livekit.example;
|
PRODUCT_BUNDLE_IDENTIFIER = io.livekit.example.flutter;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
@@ -535,6 +660,117 @@
|
|||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
D7FECD312860997500D04D1C /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "LiveKit Broadcast Extension/LiveKit Broadcast Extension.entitlements";
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = 76TVFCUKK7;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "LiveKit Broadcast Extension/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "LiveKit Broadcast Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "io.livekit.example.flutter.LiveKit-Broadcast-Extension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
D7FECD322860997500D04D1C /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "LiveKit Broadcast Extension/LiveKit Broadcast Extension.entitlements";
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = 76TVFCUKK7;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "LiveKit Broadcast Extension/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "LiveKit Broadcast Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "io.livekit.example.flutter.LiveKit-Broadcast-Extension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
D7FECD332860997500D04D1C /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = "LiveKit Broadcast Extension/LiveKit Broadcast Extension.entitlements";
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = 76TVFCUKK7;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "LiveKit Broadcast Extension/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "LiveKit Broadcast Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "io.livekit.example.flutter.LiveKit-Broadcast-Extension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
@@ -558,6 +794,16 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
D7FECD342860997500D04D1C /* Build configuration list for PBXNativeTarget "LiveKit Broadcast Extension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
D7FECD312860997500D04D1C /* Debug */,
|
||||||
|
D7FECD322860997500D04D1C /* Release */,
|
||||||
|
D7FECD332860997500D04D1C /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>RTCScreenSharingExtension</key>
|
||||||
|
<string>io.livekit.example.flutter.LiveKit-Broadcast-Extension</string>
|
||||||
|
<key>RTCAppGroupIdentifier</key>
|
||||||
|
<string>group.io.livekit.example.flutter</string>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
@@ -49,7 +55,5 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.io.livekit.example.flutter</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -90,12 +90,13 @@ class _ConnectPageState extends State<ConnectPage> {
|
|||||||
_uriCtrl.text,
|
_uriCtrl.text,
|
||||||
_tokenCtrl.text,
|
_tokenCtrl.text,
|
||||||
roomOptions: RoomOptions(
|
roomOptions: RoomOptions(
|
||||||
adaptiveStream: _adaptiveStream,
|
adaptiveStream: _adaptiveStream,
|
||||||
dynacast: _dynacast,
|
dynacast: _dynacast,
|
||||||
defaultVideoPublishOptions: VideoPublishOptions(
|
defaultVideoPublishOptions: VideoPublishOptions(
|
||||||
simulcast: _simulcast,
|
simulcast: _simulcast,
|
||||||
),
|
),
|
||||||
),
|
defaultScreenShareCaptureOptions: const ScreenShareCaptureOptions(
|
||||||
|
useiOSBroadcastExtension: true)),
|
||||||
);
|
);
|
||||||
|
|
||||||
await Navigator.push<void>(
|
await Navigator.push<void>(
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ packages:
|
|||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.9"
|
version: "0.8.10"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -225,7 +225,7 @@ packages:
|
|||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.0"
|
version: "1.0.1"
|
||||||
logging:
|
logging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
|
|
||||||
import '../track/local/audio.dart';
|
import '../track/local/audio.dart';
|
||||||
@@ -74,12 +76,26 @@ class CameraCaptureOptions extends VideoCaptureOptions {
|
|||||||
|
|
||||||
/// Options used when creating a [LocalVideoTrack] that captures the screen.
|
/// Options used when creating a [LocalVideoTrack] that captures the screen.
|
||||||
class ScreenShareCaptureOptions extends VideoCaptureOptions {
|
class ScreenShareCaptureOptions extends VideoCaptureOptions {
|
||||||
|
final bool useiOSBroadcastExtension;
|
||||||
|
|
||||||
const ScreenShareCaptureOptions({
|
const ScreenShareCaptureOptions({
|
||||||
|
this.useiOSBroadcastExtension = false,
|
||||||
VideoParameters params = VideoParametersPresets.screenShareH720FPS15,
|
VideoParameters params = VideoParametersPresets.screenShareH720FPS15,
|
||||||
}) : super(params: params);
|
}) : super(params: params);
|
||||||
|
|
||||||
ScreenShareCaptureOptions.from({required VideoCaptureOptions captureOptions})
|
ScreenShareCaptureOptions.from(
|
||||||
|
{this.useiOSBroadcastExtension = false,
|
||||||
|
required VideoCaptureOptions captureOptions})
|
||||||
: super(params: captureOptions.params);
|
: super(params: captureOptions.params);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toMediaConstraintsMap() {
|
||||||
|
var constraints = super.toMediaConstraintsMap();
|
||||||
|
if (useiOSBroadcastExtension && Platform.isIOS) {
|
||||||
|
constraints['deviceId'] = 'broadcast';
|
||||||
|
}
|
||||||
|
return constraints;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Base class for track options.
|
/// Base class for track options.
|
||||||
|
|||||||
+1
-1
@@ -218,7 +218,7 @@ packages:
|
|||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.9"
|
version: "0.8.10"
|
||||||
glob:
|
glob:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ dependencies:
|
|||||||
uuid: ^3.0.6
|
uuid: ^3.0.6
|
||||||
synchronized: ^3.0.0+2
|
synchronized: ^3.0.0+2
|
||||||
protobuf: ^2.0.1
|
protobuf: ^2.0.1
|
||||||
flutter_webrtc: ^0.8.9
|
flutter_webrtc: ^0.8.10
|
||||||
dart_webrtc: ^1.0.6
|
dart_webrtc: ^1.0.6
|
||||||
device_info_plus: ^3.2.3
|
device_info_plus: ^3.2.3
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user