From ddbd082c567675bf46930737256e850b4abd5976 Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Tue, 16 May 2023 12:04:08 +0200 Subject: [PATCH 1/8] [WIP] Socket refactor (#35) --- .../EventTransport/EventTransport.swift | 23 ++--- .../EventTransport/PhoenixTransport.swift | 30 ++---- .../Sources/MembraneRTC/Events/Event.swift | 9 +- .../Sources/MembraneRTC/MembraneRTC.swift | 99 +++++++------------ .../MembraneRTC/MembraneRTCDelegate.swift | 9 +- .../MembraneRTC/MembraneRTCError.swift | 5 - .../MembraneRTC/RTCEngineCommunication.swift | 48 ++++----- .../MembraneRTC/RTCEngineListener.swift | 3 +- .../Types/SerializedMediaEvent.swift | 1 + .../xcshareddata/swiftpm/Package.resolved | 29 ++---- MembraneVideoroomDemo/Controllers/App.swift | 48 +++++---- .../Controllers/RoomController.swift | 39 +++----- MembraneVideoroomDemo/Views/ContentView.swift | 2 +- MembraneVideoroomDemo/Views/RoomView.swift | 4 +- 14 files changed, 135 insertions(+), 214 deletions(-) delete mode 100644 MembraneRTC/Sources/MembraneRTC/MembraneRTCError.swift create mode 100644 MembraneRTC/Sources/MembraneRTC/Types/SerializedMediaEvent.swift diff --git a/MembraneRTC/Sources/MembraneRTC/EventTransport/EventTransport.swift b/MembraneRTC/Sources/MembraneRTC/EventTransport/EventTransport.swift index 04663be3..5c1f18a1 100644 --- a/MembraneRTC/Sources/MembraneRTC/EventTransport/EventTransport.swift +++ b/MembraneRTC/Sources/MembraneRTC/EventTransport/EventTransport.swift @@ -1,7 +1,7 @@ import Foundation import Promises -public enum EventTransportError: Error { +public enum PhoenixTransportError: Error { /// Thrown when user is not authorized to join the session case unauthorized @@ -12,7 +12,7 @@ public enum EventTransportError: Error { case unexpected(reason: String) } -extension EventTransportError: CustomStringConvertible { +extension PhoenixTransportError: CustomStringConvertible { public var description: String { switch self { case .unauthorized: @@ -25,19 +25,8 @@ extension EventTransportError: CustomStringConvertible { } } -/// Protocol defining a behaviour of an events' transport used for exchaning messages -/// between client and the server. -/// -/// An implementation of such transport should take an `EventTransportDelegate` as its argument -/// and pass received and parsed messages directly to the delegate. -public protocol EventTransport { - func connect(delegate: EventTransportDelegate) -> Promise - func disconnect() - func send(event: SendableEvent) -} - -/// Protocol for a delegate listening for messages received by the `EventTransport` -public protocol EventTransportDelegate: AnyObject { - func didReceive(event: ReceivableEvent) - func didReceive(error: EventTransportError) +/// Protocol for a delegate listening for messages received by the `PhoenixTransport` +public protocol PhoenixTransportDelegate: AnyObject { + func didReceive(event: SerializedMediaEvent) + func didReceive(error: PhoenixTransportError) } diff --git a/MembraneRTC/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift b/MembraneRTC/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift index 2efe009e..9b3291ed 100644 --- a/MembraneRTC/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift +++ b/MembraneRTC/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift @@ -2,8 +2,7 @@ import Foundation import Promises import SwiftPhoenixClient -/// `EventTransport` implementation utilizing `Phoenix` socket and a channel. -public class PhoenixTransport: EventTransport { +public class PhoenixTransport { enum ConnectionState { case uninitialized, connecting, connected, closed, error } @@ -16,7 +15,7 @@ public class PhoenixTransport: EventTransport { var channel: Channel? var connectionState: ConnectionState = .uninitialized - weak var delegate: EventTransportDelegate? + weak var delegate: PhoenixTransportDelegate? let queue = DispatchQueue(label: "membrane.rtc.transport", qos: .background) @@ -28,10 +27,10 @@ public class PhoenixTransport: EventTransport { endPoint: url, transport: { URLSessionTransport(url: $0) }, paramsClosure: { params }) } - public func connect(delegate: EventTransportDelegate) -> Promise { + public func connect(delegate: PhoenixTransportDelegate) -> Promise { return Promise(on: queue) { resolve, fail in guard case .uninitialized = self.connectionState else { - fail(EventTransportError.unexpected(reason: "Tried to connect on a pending socket")) + fail(PhoenixTransportError.unexpected(reason: "Tried to connect on a pending socket")) return } @@ -58,7 +57,7 @@ public class PhoenixTransport: EventTransport { "error", callback: { _ in self.connectionState = .error - fail(EventTransportError.connectionError) + fail(PhoenixTransportError.connectionError) }) self.channel = channel @@ -67,12 +66,7 @@ public class PhoenixTransport: EventTransport { self.channel!.on( "mediaEvent", callback: { message in - guard let event: ReceivableEvent = Events.deserialize(payload: Payload(message.payload)) - else { - return - } - - self.delegate?.didReceive(event: event) + self.delegate?.didReceive(event: message.payload["data"] as! SerializedMediaEvent) }) } } @@ -89,7 +83,7 @@ public class PhoenixTransport: EventTransport { connectionState = .closed } - public func send(event: SendableEvent) { + public func send(event: SerializedMediaEvent) { guard connectionState == .connected, let channel = channel else { @@ -97,13 +91,7 @@ public class PhoenixTransport: EventTransport { return } - let data = try! JSONEncoder().encode(event.serialize()) - - guard let dataPayload = String(data: data, encoding: .utf8) else { - return - } - - channel.push("mediaEvent", payload: ["data": dataPayload]) + channel.push("mediaEvent", payload: ["data": event]) } } @@ -118,6 +106,6 @@ extension PhoenixTransport { func onError(_: Error) { connectionState = .closed - delegate?.didReceive(error: EventTransportError.connectionError) + delegate?.didReceive(error: PhoenixTransportError.connectionError) } } diff --git a/MembraneRTC/Sources/MembraneRTC/Events/Event.swift b/MembraneRTC/Sources/MembraneRTC/Events/Event.swift index 7f828897..50362e02 100644 --- a/MembraneRTC/Sources/MembraneRTC/Events/Event.swift +++ b/MembraneRTC/Sources/MembraneRTC/Events/Event.swift @@ -77,13 +77,8 @@ public enum Events { - to recognize the nested event's type - to finally deserialize the payload into an explicit event */ - public static func deserialize(payload: Payload) -> ReceivableEvent? { - guard let rawData = payload["data"] as? String else { - sdkLogger.error("Failed to extract 'data' field from json payload: \(payload)") - return nil - } - - let data = rawData.data(using: .utf8)! + public static func deserialize(payload: String) -> ReceivableEvent? { + let data = payload.data(using: .utf8)! guard let base: ReceivableEventBase = decodeEvent(from: data) else { sdkLogger.error("Failed to decode ReceivableEventBase") diff --git a/MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift b/MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift index ab2af8a1..369224ca 100644 --- a/MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift +++ b/MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift @@ -22,37 +22,30 @@ internal let pcLogPrefix = "[PeerConnection]" /// /// It is recommended to request necessary audio and video tracks before joining the room but it does not mean it can't be done afterwards (in case of screencast) /// -/// Once the user received `onConnected` notification they can call the `join` method to initialize joining the session. +/// Once the user created the MembraneRTC client and connected to the server transport layer they can call the `join` method to initialize joining the session. /// After receiving `onJoinSuccess` a user will receive notification about various peers joining/leaving the session, new tracks being published and ready for playback /// or going inactive. public class MembraneRTC: MulticastDelegate, ObservableObject, RTCEngineListener, PeerConnectionListener { enum State { - case uninitialized case awaitingJoin case connected case disconnected } - public struct ConnectOptions { - let transport: EventTransport - let config: Metadata + public struct CreateOptions { let encoder: Encoder - public init(transport: EventTransport, config: Metadata, encoder: Encoder = Encoder.DEFAULT) { - self.transport = transport - self.config = config + public init(encoder: Encoder = Encoder.DEFAULT) { self.encoder = encoder } } var state: State - private var eventTransport: EventTransport - private lazy var engineCommunication: RTCEngineCommunication = { - return RTCEngineCommunication(transport: eventTransport, engineListener: self) + return RTCEngineCommunication(engineListener: self) }() // a common stream ID used for all non-screenshare and audio tracks @@ -83,22 +76,13 @@ public class MembraneRTC: MulticastDelegate, ObservableObje config: self.config, peerConnectionFactory: self.peerConnectionFactoryWrapper, peerConnectionListener: self) }() - internal init( - eventTransport: EventTransport, config: RTCConfiguration, peerMetadata: Metadata, - encoder: Encoder - ) { - // RTCSetMinDebugLogLevel(.error) + internal init(config: RTCConfiguration, encoder: Encoder) { sdkLogger.logLevel = .info - state = .uninitialized - - self.eventTransport = eventTransport + state = .awaitingJoin self.config = config - // setup local peer - localPeer = localPeer.with(metadata: peerMetadata) - peerConnectionFactoryWrapper = PeerConnectionFactoryWrapper(encoder: encoder) self.encoder = encoder @@ -107,26 +91,22 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } /** - Initializes the connection with the `Membrane RTC Engine` transport layer - and sets up local audio and video track. + Initializes MembraneRTC client and sets up local audio and video track. Should not be confused with joining the actual room, which is a separate process. - Parameters: - - with: Connection options, consists of an `EventTransport` instance that will be used for relaying media events, arbitrary `config` metadata used by `Membrane RTC Engine` for connection and `encoder` type + - with: Create options, consists of `encoder` type - delegate: The delegate that will receive all notification emitted by `MembraneRTC` client - - Returns: `MembraneRTC` client instance in connecting state + - Returns: `MembraneRTC` client instance */ - public static func connect(with options: ConnectOptions, delegate: MembraneRTCDelegate) + public static func create(with options: CreateOptions = CreateOptions(), delegate: MembraneRTCDelegate) -> MembraneRTC { - let client = MembraneRTC( - eventTransport: options.transport, config: RTCConfiguration(), peerMetadata: options.config, - encoder: options.encoder) + let client = MembraneRTC(config: RTCConfiguration(), encoder: options.encoder) client.add(delegate: delegate) - client.connect() return client } @@ -141,20 +121,20 @@ public class MembraneRTC: MulticastDelegate, ObservableObje /// Initiaites join process once the client has successfully connected. /// /// Once completed either `onJoinSuccess` or `onJoinError` of client's delegate gets invovked. - public func join() { + public func join(peerMetadata: Metadata) { guard state == .awaitingJoin else { return } - engineCommunication.join(peerMetadata: localPeer.metadata) + localPeer = localPeer.with(metadata: peerMetadata) + + engineCommunication.join(peerMetadata: peerMetadata) } /// Disconnects from the `Membrane RTC Engine` transport and closes the exisitng `RTCPeerConnection` /// /// Once the `disconnect` gets invoked the client can't be reused and user should create a new client instance instead. public func disconnect() { - engineCommunication.disconnect() - localTracks.forEach { track in track.stop() } @@ -162,6 +142,17 @@ public class MembraneRTC: MulticastDelegate, ObservableObje peerConnectionManager.close() } + /** + * Feeds media event received from RTC Engine to MembraneWebRTC. + * This function should be called whenever some media event from RTC Engine + * was received and can result in MembraneWebRTC generating some other + * media events. + * @param mediaEvent - String data received over custom signalling layer. + */ + public func receiveMediaEvent(mediaEvent: SerializedMediaEvent) { + engineCommunication.onEvent(serializedEvent: mediaEvent) + } + /** Creates a new video track utilizing device's specified camera. @@ -388,21 +379,6 @@ public class MembraneRTC: MulticastDelegate, ObservableObje peerConnectionManager.setEncodingBandwidth(trackId: trackId, encoding: encoding, bandwidth: bandwidth) } - internal func connect() { - // initiate a transport connection - engineCommunication.connect().then { - self.notify { - self.state = .awaitingJoin - - $0.onConnected() - } - }.catch { error in - self.notify { - $0.onError(.transport(error.localizedDescription)) - } - } - } - /// Adds given broadcast track to the peer connection and forces track renegotiation. private func setupScreencastTrack(track: LocalScreenBroadcastTrack, metadata: Metadata) { let screencastStreamId = UUID().uuidString @@ -452,6 +428,12 @@ public class MembraneRTC: MulticastDelegate, ObservableObje RTCSetMinDebugLogLevel(severity) } + func onSendMediaEvent(event: SerializedMediaEvent) { + notify { + $0.onSendMediaEvent(event: event) + } + } + func onPeerAccepted(peerId: String, peersInRoom: [Peer]) { localPeer = localPeer.with(id: peerId) @@ -546,9 +528,8 @@ public class MembraneRTC: MulticastDelegate, ObservableObje integratedTurnServers: integratedTurnServers, tracksTypes: tracksTypes, localTracks: localTracks ) { sdp, midToTrackId, error in if let err = error { - self.notify { - $0.onError(.rtc(err.localizedDescription)) - } + sdkLogger.error("Failed to create sdp offer: \(err)") + return } if let sdp = sdp, let midToTrackId = midToTrackId { @@ -671,18 +652,6 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } } - func onError(error: EventTransportError) { - notify { - $0.onError(.transport(error.description)) - } - } - - func onClose() { - notify { - $0.onError(.transport("Transport has been closed")) - } - } - /// Sends the local ice candidate to the `Membrane RTC Engine` instance via transport layer. func onLocalIceCandidate(candidate: RTCIceCandidate) { engineCommunication.localCandidate(sdp: candidate.sdp, sdpMLineIndex: candidate.sdpMLineIndex) diff --git a/MembraneRTC/Sources/MembraneRTC/MembraneRTCDelegate.swift b/MembraneRTC/Sources/MembraneRTC/MembraneRTCDelegate.swift index 872bb2ae..a1cb25f1 100644 --- a/MembraneRTC/Sources/MembraneRTC/MembraneRTCDelegate.swift +++ b/MembraneRTC/Sources/MembraneRTC/MembraneRTCDelegate.swift @@ -1,7 +1,7 @@ /// Delegate responsible for receiving notification from `MembraneRTC` client. public protocol MembraneRTCDelegate { - /// Callback invoked when client has successfully connected via transport layer. - func onConnected() + /// Called each time MembraneWebRTC need to send some data to the server. + func onSendMediaEvent(event: SerializedMediaEvent) /// Callback invoked when the client has been approved to participate in session. func onJoinSuccess(peerID: String, peersInRoom: [Peer]) @@ -43,11 +43,6 @@ public protocol MembraneRTCDelegate { ///estimation - client's available incoming bitrate estimated ///by the server. It's measured in bits per second. func onBandwidthEstimationChanged(estimation: Int) - - /// Callback invoked when an errors happens. - /// - /// For more information about the error type please refere to `MembraneRTCError`. - func onError(_ error: MembraneRTCError) } extension MembraneRTCDelegate { diff --git a/MembraneRTC/Sources/MembraneRTC/MembraneRTCError.swift b/MembraneRTC/Sources/MembraneRTC/MembraneRTCError.swift deleted file mode 100644 index 2839dfb3..00000000 --- a/MembraneRTC/Sources/MembraneRTC/MembraneRTCError.swift +++ /dev/null @@ -1,5 +0,0 @@ -public enum MembraneRTCError { - case rtc(String) - case transport(String) - case unknown(String) -} diff --git a/MembraneRTC/Sources/MembraneRTC/RTCEngineCommunication.swift b/MembraneRTC/Sources/MembraneRTC/RTCEngineCommunication.swift index 10f995fd..18935c56 100644 --- a/MembraneRTC/Sources/MembraneRTC/RTCEngineCommunication.swift +++ b/MembraneRTC/Sources/MembraneRTC/RTCEngineCommunication.swift @@ -1,52 +1,56 @@ +import Foundation import Promises -internal class RTCEngineCommunication: EventTransportDelegate { - let transport: EventTransport +internal class RTCEngineCommunication { let engineListener: RTCEngineListener - init(transport: EventTransport, engineListener: RTCEngineListener) { - self.transport = transport + init(engineListener: RTCEngineListener) { self.engineListener = engineListener } - func connect() -> Promise { - return transport.connect(delegate: self) - } - - func disconnect() { - transport.disconnect() - } - func join(peerMetadata: Metadata) { - transport.send(event: JoinEvent(metadata: peerMetadata)) + sendEvent(event: JoinEvent(metadata: peerMetadata)) } func updatePeerMetadata(peerMetadata: Metadata) { - transport.send(event: UpdatePeerMetadata(metadata: peerMetadata)) + sendEvent(event: UpdatePeerMetadata(metadata: peerMetadata)) } func updateTrackMetadata(trackId: String, trackMetadata: Metadata) { - transport.send(event: UpdateTrackMetadata(trackId: trackId, trackMetadata: trackMetadata)) + sendEvent(event: UpdateTrackMetadata(trackId: trackId, trackMetadata: trackMetadata)) } func setTargetTrackEncoding(trackId: String, encoding: TrackEncoding) { - transport.send(event: SelectEncodingEvent(trackId: trackId, encoding: encoding.description)) + sendEvent(event: SelectEncodingEvent(trackId: trackId, encoding: encoding.description)) } func renegotiateTracks() { - transport.send(event: RenegotiateTracksEvent()) + sendEvent(event: RenegotiateTracksEvent()) } func localCandidate(sdp: String, sdpMLineIndex: Int32) { - transport.send(event: LocalCandidateEvent(candidate: sdp, sdpMLineIndex: sdpMLineIndex)) + sendEvent(event: LocalCandidateEvent(candidate: sdp, sdpMLineIndex: sdpMLineIndex)) } func sdpOffer(sdp: String, trackIdToTrackMetadata: [String: Metadata], midToTrackId: [String: String]) { - transport.send( + sendEvent( event: SdpOfferEvent(sdp: sdp, trackIdToTrackMetadata: trackIdToTrackMetadata, midToTrackId: midToTrackId)) } - func didReceive(event: ReceivableEvent) { + private func sendEvent(event: SendableEvent) { + let data = try! JSONEncoder().encode(event.serialize()) + + guard let dataPayload = String(data: data, encoding: .utf8) else { + return + } + engineListener.onSendMediaEvent(event: dataPayload) + } + + func onEvent(serializedEvent: SerializedMediaEvent) { + guard let event = Events.deserialize(payload: serializedEvent) else { + sdkLogger.error("Failed to decode event \(serializedEvent)") + return + } switch event.type { case .PeerAccepted: let peerAccepted = event as! PeerAcceptedEvent @@ -104,8 +108,4 @@ internal class RTCEngineCommunication: EventTransportDelegate { return } } - - func didReceive(error: EventTransportError) { - engineListener.onError(error: error) - } } diff --git a/MembraneRTC/Sources/MembraneRTC/RTCEngineListener.swift b/MembraneRTC/Sources/MembraneRTC/RTCEngineListener.swift index 84000457..8a4472be 100644 --- a/MembraneRTC/Sources/MembraneRTC/RTCEngineListener.swift +++ b/MembraneRTC/Sources/MembraneRTC/RTCEngineListener.swift @@ -1,4 +1,5 @@ internal protocol RTCEngineListener { + func onSendMediaEvent(event: SerializedMediaEvent) func onPeerAccepted(peerId: String, peersInRoom: [Peer]) func onPeerDenied() func onPeerJoined(peer: Peer) @@ -14,6 +15,4 @@ internal protocol RTCEngineListener { func onVadNotification(trackId: String, status: String) func onBandwidthEstimation(estimation: Int) func onRemoved(peerId: String, reason: String) - func onError(error: EventTransportError) - func onClose() } diff --git a/MembraneRTC/Sources/MembraneRTC/Types/SerializedMediaEvent.swift b/MembraneRTC/Sources/MembraneRTC/Types/SerializedMediaEvent.swift new file mode 100644 index 00000000..40120f81 --- /dev/null +++ b/MembraneRTC/Sources/MembraneRTC/Types/SerializedMediaEvent.swift @@ -0,0 +1 @@ +public typealias SerializedMediaEvent = String diff --git a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3b012625..6b4b6052 100644 --- a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/google/promises.git", "state": { "branch": null, - "revision": "3e4e743631e86c8c70dbc6efdc7beaa6e90fd3bb", - "version": "2.1.1" + "revision": "ec957ccddbcc710ccc64c9dcbd4c7006fcf8b73a", + "version": "2.2.0" } }, { @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/daltoniam/Starscream.git", "state": { "branch": null, - "revision": "e6b65c6d9077ea48b4a7bdda8994a1d3c6969c8d", - "version": "3.1.1" + "revision": "a063fda2b8145a231953c20e7a646be254365396", + "version": "3.1.2" } }, { @@ -42,8 +42,8 @@ "repositoryURL": "https://github.com/apple/swift-collections.git", "state": { "branch": null, - "revision": "48254824bb4248676bf7ce56014ff57b142b77eb", - "version": "1.0.2" + "revision": "937e904258d22af6e447a0b72c0bc67583ef64a2", + "version": "1.0.4" } }, { @@ -51,17 +51,8 @@ "repositoryURL": "https://github.com/apple/swift-log.git", "state": { "branch": null, - "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", - "version": "1.4.2" - } - }, - { - "package": "swift-nio-zlib-support", - "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", - "state": { - "branch": null, - "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", - "version": "1.0.0" + "revision": "32e8d724467f8fe623624570367e3d50c5638e46", + "version": "1.5.2" } }, { @@ -69,8 +60,8 @@ "repositoryURL": "https://github.com/apple/swift-protobuf.git", "state": { "branch": null, - "revision": "e1499bc69b9040b29184f7f2996f7bab467c1639", - "version": "1.19.0" + "revision": "0af9125c4eae12a4973fb66574c53a54962a9e1e", + "version": "1.21.0" } }, { diff --git a/MembraneVideoroomDemo/Controllers/App.swift b/MembraneVideoroomDemo/Controllers/App.swift index 247da124..93bdf799 100644 --- a/MembraneVideoroomDemo/Controllers/App.swift +++ b/MembraneVideoroomDemo/Controllers/App.swift @@ -6,35 +6,43 @@ final class AppController: ObservableObject { public static let shared = AppController() public private(set) var client: MembraneRTC? + public private(set) var transport: PhoenixTransport? + public private(set) var displayName: String = "" enum State { case awaiting, loading, connected, disconnected, error } @Published private(set) var state: State + @Published var errorMessage: String? private init() { state = .awaiting } public func connect(room: String, displayName: String) { + self.displayName = displayName let engineUrl = Constants.getRtcEngineUrl().trimmingCharacters(in: CharacterSet(charactersIn: "/")) let transportUrl = "\(engineUrl)/socket" - let client = MembraneRTC.connect( - with: MembraneRTC.ConnectOptions( - transport: PhoenixTransport( - url: transportUrl, topic: "room:\(room)", params: [:], channelParams: ["isSimulcastOn": true]), - config: .init(["displayName": displayName]) - ), - delegate: self - ) - + let transport = PhoenixTransport( + url: transportUrl, topic: "room:\(room)", params: [:], channelParams: ["isSimulcastOn": true]) DispatchQueue.main.async { self.state = .loading - self.client = client } + transport.connect(delegate: self).then { + DispatchQueue.main.async { + self.client = MembraneRTC.create(delegate: self) + self.transport = transport + self.state = .connected + } + }.catch { error in + DispatchQueue.main.async { + self.state = .error + } + } + } public func disconnect() { @@ -43,6 +51,8 @@ final class AppController: ObservableObject { return } + self.transport?.disconnect() + client.remove(delegate: self) client.disconnect() @@ -70,10 +80,8 @@ final class AppController: ObservableObject { } extension AppController: MembraneRTCDelegate { - func onConnected() { - DispatchQueue.main.async { - self.state = .connected - } + func onSendMediaEvent(event: SerializedMediaEvent) { + transport?.send(event: event) } func onJoinSuccess(peerID _: String, peersInRoom _: [Peer]) {} @@ -93,10 +101,14 @@ extension AppController: MembraneRTCDelegate { func onPeerLeft(peer _: Peer) {} func onPeerUpdated(peer _: Peer) {} +} - func onError(_: MembraneRTCError) { - DispatchQueue.main.async { - self.state = .error - } +extension AppController: PhoenixTransportDelegate { + func didReceive(error: PhoenixTransportError) { + state = .error + } + + func didReceive(event: SerializedMediaEvent) { + self.client?.receiveMediaEvent(mediaEvent: event) } } diff --git a/MembraneVideoroomDemo/Controllers/RoomController.swift b/MembraneVideoroomDemo/Controllers/RoomController.swift index e5d1bcdd..05c3ecf8 100644 --- a/MembraneVideoroomDemo/Controllers/RoomController.swift +++ b/MembraneVideoroomDemo/Controllers/RoomController.swift @@ -57,7 +57,7 @@ class RoomController: ObservableObject { @Published var screencastSimulcastConfig: SimulcastConfig = SimulcastConfig( enabled: false, activeEncodings: []) - init(_ room: MembraneRTC) { + init(_ room: MembraneRTC, _ displayName: String) { self.room = room participants = [:] participantVideos = [] @@ -66,18 +66,19 @@ class RoomController: ObservableObject { isCameraEnabled = true isScreensharingEnabled = false - let localPeer = room.currentPeer() - let videoTrackMetadata = [ - "user_id": localPeer.metadata["displayName"] ?? "UNKNOWN", "active": true, "type": "camera", - ] - let audioTrackMetadata = [ - "user_id": localPeer.metadata["displayName"] ?? "UNKNOWN", "active": true, "type": "audio", - ] + let videoTrackMetadata = + [ + "user_id": displayName, "active": true, "type": "camera", + ] as [String: Any] + let audioTrackMetadata = + [ + "user_id": displayName, "active": true, "type": "audio", + ] as [String: Any] let preset = VideoParameters.presetHD43 let videoParameters = VideoParameters( dimensions: preset.dimensions.flip(), - maxBandwidth: .SimulcastBandwidthLimit(["l": 150, "m": 500, "h": 1500]), + maxBandwidth: TrackBandwidthLimit.SimulcastBandwidthLimit(["l": 150, "m": 500, "h": 1500]), simulcastConfig: videoSimulcastConfig ) @@ -87,7 +88,7 @@ class RoomController: ObservableObject { room.add(delegate: self) - self.room?.join() + self.room?.join(peerMetadata: .init(["displayName": displayName])) } func enableTrack(_ type: LocalTrackType, enabled: Bool) { @@ -320,7 +321,8 @@ class RoomController: ObservableObject { } extension RoomController: MembraneRTCDelegate { - func onConnected() {} + + func onSendMediaEvent(event: SerializedMediaEvent) {} func onJoinSuccess(peerID: String, peersInRoom: [Peer]) { localParticipantId = peerID @@ -492,21 +494,6 @@ extension RoomController: MembraneRTCDelegate { func onPeerUpdated(peer _: Peer) {} - func onError(_ error: MembraneRTCError) { - DispatchQueue.main.async { - switch error { - case .rtc(let message): - self.errorMessage = message - - case .transport(let message): - self.errorMessage = message - - case .unknown(let message): - self.errorMessage = message - } - } - } - private func toggleTrackEncoding( simulcastConfig: SimulcastConfig, trackId: String, encoding: TrackEncoding ) -> SimulcastConfig { diff --git a/MembraneVideoroomDemo/Views/ContentView.swift b/MembraneVideoroomDemo/Views/ContentView.swift index e4e6d12a..0e28dae8 100644 --- a/MembraneVideoroomDemo/Views/ContentView.swift +++ b/MembraneVideoroomDemo/Views/ContentView.swift @@ -9,7 +9,7 @@ struct ContentView: View { switch appCtrl.state { case .connected: - RoomView(appCtrl.client!) + RoomView(appCtrl.client!, appCtrl.displayName) default: ConnectView() } diff --git a/MembraneVideoroomDemo/Views/RoomView.swift b/MembraneVideoroomDemo/Views/RoomView.swift index 7a342c10..ce3ce14d 100644 --- a/MembraneVideoroomDemo/Views/RoomView.swift +++ b/MembraneVideoroomDemo/Views/RoomView.swift @@ -42,9 +42,9 @@ struct RoomView: View { @ObservedObject var orientationReceiver: OrientationReceiver @State private var localDimensions: Dimensions? - init(_ room: MembraneRTC) { + init(_ room: MembraneRTC, _ displayName: String) { orientationReceiver = OrientationReceiver() - self.room = RoomController(room) + self.room = RoomController(room, displayName) } @ViewBuilder From 3fb10c66e4cd369d92d9a2a49d3f1265d50dd278 Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Tue, 6 Jun 2023 14:47:39 +0200 Subject: [PATCH 2/8] Expose swift package (#36) * Expose swift package * fix? * cant believe this works * Test docs * fix docs * fix docs --- .github/workflows/publish_docs.yaml | 6 +- .github/workflows/run_lint_and_tests.yaml | 4 +- .gitignore | 6 +- MembraneRTC.podspec | 4 +- MembraneRTC/.gitignore | 7 - .../xcschemes/MembraneRTC.xcscheme | 77 --------- MembraneRTC/README.md | 31 ---- .../project.pbxproj | 42 +++-- .../xcshareddata/swiftpm/Package.resolved | 150 ++++++++---------- .../contents.xcworkspacedata | 3 + .../xcshareddata/swiftpm/Package.resolved | 22 ++- Package.resolved | 97 +++++++++++ MembraneRTC/Package.swift => Package.swift | 1 + .../Documentation.docc/MembraneRTC.md | 0 .../MembraneRTC/Constants.swift | 0 .../EventTransport/EventTransport.swift | 0 .../EventTransport/PhoenixTransport.swift | 0 .../MembraneRTC/Events/Event.swift | 0 .../MembraneRTC/IPC/IPC.swift | 0 .../MembraneRTC/IPC/broadcast_ipc.pb.swift | 0 .../MembraneRTC/IPC/broadcast_ipc.proto | 0 .../Media/BroadcastSampleSource.swift | 0 .../Media/Capturers/CameraCapturer.swift | 0 .../Media/Capturers/FileCapturer.swift | 0 .../Capturers/ScreenBroadcastCapturer.swift | 0 .../Media/Capturers/ScreenCapturer.swift | 0 .../Media/Capturers/VideoCapturer.swift | 0 .../MembraneRTC/Media/Dimensions.swift | 0 .../ScreenBroadcastNotificationReceiver.swift | 0 .../MembraneRTC/Media/Tracks/AudioTrack.swift | 0 .../Media/Tracks/LocalAudioTrack.swift | 0 .../Tracks/LocalScreenBroadcastTrack.swift | 0 .../MembraneRTC/Media/Tracks/LocalTrack.swift | 0 .../Media/Tracks/LocalVideoTrack.swift | 0 .../Media/Tracks/MediaTrackProvider.swift | 0 .../Media/Tracks/RemoteAudioTrack.swift | 0 .../Media/Tracks/RemoteTrack.swift | 0 .../Media/Tracks/RemoteVideoTrack.swift | 0 .../MembraneRTC/Media/Tracks/VideoTrack.swift | 0 .../MembraneRTC/Media/VideoParameters.swift | 0 .../MembraneRTC/MembraneRTC.swift | 0 .../MembraneRTC/MembraneRTCDelegate.swift | 0 .../PeerConnectionFactoryWrapper.swift | 0 .../MembraneRTC/PeerConnectionListener.swift | 0 .../MembraneRTC/PeerConnectionManager.swift | 0 .../MembraneRTC/RTCEngineCommunication.swift | 0 .../MembraneRTC/RTCEngineListener.swift | 0 .../MembraneRTC/Types/AnyJson.swift | 0 .../MembraneRTC/Types/Encoder.swift | 0 .../MembraneRTC/Types/EncodingReason.swift | 0 .../MembraneRTC/Types/Metadata.swift | 0 .../MembraneRTC/Types/Peer.swift | 0 .../MembraneRTC/Types/RTCStats.swift | 0 .../Types/SerializedMediaEvent.swift | 0 .../MembraneRTC/Types/SimulcastConfig.swift | 0 .../Types/TrackBandwidthLimit.swift | 0 .../MembraneRTC/Types/TrackContext.swift | 0 .../MembraneRTC/Types/VadStatus.swift | 0 .../MembraneRTC/UI/SwiftUIVideoView.swift | 0 .../MembraneRTC/UI/VideoView.swift | 0 .../Utilities/MulticastDelegate.swift | 0 .../Utilities/SimulcastUtils.swift | 0 62 files changed, 215 insertions(+), 235 deletions(-) delete mode 100644 MembraneRTC/.gitignore delete mode 100644 MembraneRTC/.swiftpm/xcode/xcshareddata/xcschemes/MembraneRTC.xcscheme delete mode 100644 MembraneRTC/README.md create mode 100644 Package.resolved rename MembraneRTC/Package.swift => Package.swift (95%) rename {MembraneRTC/Sources => Sources}/Documentation.docc/MembraneRTC.md (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Constants.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/EventTransport/EventTransport.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/EventTransport/PhoenixTransport.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Events/Event.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/IPC/IPC.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/IPC/broadcast_ipc.pb.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/IPC/broadcast_ipc.proto (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/BroadcastSampleSource.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Capturers/CameraCapturer.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Capturers/FileCapturer.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Capturers/ScreenCapturer.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Capturers/VideoCapturer.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Dimensions.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/ScreenBroadcastNotificationReceiver.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/AudioTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/LocalAudioTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/LocalScreenBroadcastTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/LocalTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/LocalVideoTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/MediaTrackProvider.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/RemoteAudioTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/RemoteTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/RemoteVideoTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/Tracks/VideoTrack.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Media/VideoParameters.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/MembraneRTC.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/MembraneRTCDelegate.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/PeerConnectionFactoryWrapper.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/PeerConnectionListener.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/PeerConnectionManager.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/RTCEngineCommunication.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/RTCEngineListener.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/AnyJson.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/Encoder.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/EncodingReason.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/Metadata.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/Peer.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/RTCStats.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/SerializedMediaEvent.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/SimulcastConfig.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/TrackBandwidthLimit.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/TrackContext.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Types/VadStatus.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/UI/SwiftUIVideoView.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/UI/VideoView.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Utilities/MulticastDelegate.swift (100%) rename {MembraneRTC/Sources => Sources}/MembraneRTC/Utilities/SimulcastUtils.swift (100%) diff --git a/.github/workflows/publish_docs.yaml b/.github/workflows/publish_docs.yaml index 3fc43c95..367c3e4e 100644 --- a/.github/workflows/publish_docs.yaml +++ b/.github/workflows/publish_docs.yaml @@ -2,8 +2,6 @@ name: Deploy Docs on: push: - tags: - - "*" jobs: build: @@ -12,7 +10,7 @@ jobs: - uses: actions/checkout@v3 - name: Build Docs - run: mkdir MembraneRTC/docs && xcodebuild docbuild -scheme MembraneRTC -destination generic/platform=iOS OTHER_DOCC_FLAGS="--transform-for-static-hosting --output-path docs --hosting-base-path membrane-webrtc-ios" + run: mkdir docs && rm -rf MembraneVideoroomDemo.xcodeproj MembraneVideoroomDemo.xcworkspace MembraneVideoroomDemo && xcodebuild docbuild -scheme MembraneRTC -destination generic/platform=iOS OTHER_DOCC_FLAGS="--transform-for-static-hosting --output-path docs --hosting-base-path membrane-webrtc-ios" - name: Install coreutils run: brew install coreutils @@ -25,5 +23,5 @@ jobs: env: REPO: self BRANCH: gh-pages - FOLDER: MembraneRTC/docs + FOLDER: docs GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/run_lint_and_tests.yaml b/.github/workflows/run_lint_and_tests.yaml index aa34c56f..c0695555 100644 --- a/.github/workflows/run_lint_and_tests.yaml +++ b/.github/workflows/run_lint_and_tests.yaml @@ -15,10 +15,10 @@ jobs: run: cp Release.xcconfig Debug.xcconfig - name: Run formatter - run: swift-format format -i -r ./MembraneRTC/Sources/**/*.swift --configuration swift-format-config.json + run: swift-format format -i -r ./Sources/**/*.swift --configuration swift-format-config.json - name: Run lint - run: swift-format lint -r ./MembraneRTC/Sources/**/*.swift --configuration swift-format-config.json + run: swift-format lint -r ./Sources/**/*.swift --configuration swift-format-config.json - name: Run tests run: set -o pipefail && xcodebuild test -scheme MembraneVideoroomDemo -destination 'platform=iOS Simulator,name=iPhone 13,OS=16.2' -workspace 'MembraneVideoroomDemo.xcworkspace' -sdk iphonesimulator | xcbeautify diff --git a/.gitignore b/.gitignore index fc9a2cf0..6d6264a2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,8 @@ node_modules build docs xcuserdata -Debug.xcconfig \ No newline at end of file +Debug.xcconfig +.swiftpm +/.build +/Packages +DerivedData/ \ No newline at end of file diff --git a/MembraneRTC.podspec b/MembraneRTC.podspec index b341ba56..9c4e6582 100644 --- a/MembraneRTC.podspec +++ b/MembraneRTC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '13.0' s.swift_version = '5.0' - s.source_files = 'MembraneRTC/Sources/MembraneRTC/**/*' + s.source_files = 'Sources/MembraneRTC/**/*' s.dependency 'WebRTC-SDK', '104.5112.15' s.dependency 'SwiftProtobuf' s.dependency 'PromisesSwift' @@ -30,6 +30,6 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { 'ENABLE_BITCODE' => 'NO' } s.subspec "Broadcast" do |spec| - spec.source_files = "MembraneRTC/Sources/MembraneRTC/Media/BroadcastSampleSource.swift", "MembraneRTC/Sources/MembraneRTC/IPC/**/*.{h,m,mm,swift}" + spec.source_files = "Sources/MembraneRTC/Media/BroadcastSampleSource.swift", "Sources/MembraneRTC/IPC/**/*.{h,m,mm,swift}" end end diff --git a/MembraneRTC/.gitignore b/MembraneRTC/.gitignore deleted file mode 100644 index bb460e7b..00000000 --- a/MembraneRTC/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -/.build -/Packages -/*.xcodeproj -xcuserdata/ -DerivedData/ -.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/MembraneRTC/.swiftpm/xcode/xcshareddata/xcschemes/MembraneRTC.xcscheme b/MembraneRTC/.swiftpm/xcode/xcshareddata/xcschemes/MembraneRTC.xcscheme deleted file mode 100644 index edc0766b..00000000 --- a/MembraneRTC/.swiftpm/xcode/xcshareddata/xcschemes/MembraneRTC.xcscheme +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MembraneRTC/README.md b/MembraneRTC/README.md deleted file mode 100644 index 199609bc..00000000 --- a/MembraneRTC/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# MembraneRTC - -A package containing a `MembraneRTCEngine` iOS client. - -## Functionalities -The package provides all primitives necessary for communicating with the backend service -which should eventually result in receiving WebRTC media streams that can be then played in the target application. - -The main class is `MembraneRTC` which is the main client's controller. It is responsible for managing a transport connection -with the server and receiving/sending necessary events necessary for obtaining a valid RTC connection. - -To make usage of the client one must implement a `MembraneRTCDelegate` delegate which will notify the listener about: -- new peers joining/leaving the videoroom -- new/old media tracks from present peers -- connection's state and potential connection's errors - -### Transport -Besides WebRTC traffic which is based on UDP we need a reliable transport with the backend service that -will relay `MembraneRTCEngine` events. - -The package provides `EventTransport` protocol which can be used to implement a custom transport layer with arbitrary backend -implementing the `MembraneRTCEngine`. - -By default the package provides a `PhoenixTransport` which is based on `Phoenix Framework` socket and channels mechanism -which is 100% compatible with the Membrane's videoroom example. - -### Displaying the video streams -To display the video streams one can use provided classes: -- `VideoView` which is a `UIKit` view -- 'SwiftUIVideoView` which is a SwiftUI wrapper around `VideoView` - diff --git a/MembraneVideoroomDemo.xcodeproj/project.pbxproj b/MembraneVideoroomDemo.xcodeproj/project.pbxproj index 32e4dbc5..85ec7bcc 100644 --- a/MembraneVideoroomDemo.xcodeproj/project.pbxproj +++ b/MembraneVideoroomDemo.xcodeproj/project.pbxproj @@ -7,8 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 3B0148B927BA4F6A00907A8B /* MembraneRTC in Frameworks */ = {isa = PBXBuildFile; productRef = 3B0148B827BA4F6A00907A8B /* MembraneRTC */; }; - 3B0148BB27BA4F7300907A8B /* MembraneRTC in Frameworks */ = {isa = PBXBuildFile; productRef = 3B0148BA27BA4F7300907A8B /* MembraneRTC */; }; 3B04D3942798190F00E2B755 /* SwiftPhoenixClient in Frameworks */ = {isa = PBXBuildFile; productRef = 3B04D3932798190F00E2B755 /* SwiftPhoenixClient */; }; 3B1642DB27A134C4008BBBA7 /* RoomController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1642DA27A134C4008BBBA7 /* RoomController.swift */; }; 3B16A1DC2796C42B0095941F /* RoomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B16A1BF2796C42B0095941F /* RoomView.swift */; }; @@ -34,6 +32,8 @@ 3BCCBEF92795701600A0AD4C /* Promises in Frameworks */ = {isa = PBXBuildFile; productRef = 3BCCBEF82795701600A0AD4C /* Promises */; }; 3BD7249327AAD3DE00AFE9D9 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BD7249227AAD3DE00AFE9D9 /* logo.png */; }; 3BDAC1E027A2FCE200A2BB0D /* ParticipantVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDAC1DF27A2FCE200A2BB0D /* ParticipantVideoView.swift */; }; + 44788B4E2A27A12C00C43DD4 /* MembraneRTC in Frameworks */ = {isa = PBXBuildFile; productRef = 44788B4D2A27A12C00C43DD4 /* MembraneRTC */; }; + 44788B502A27A13100C43DD4 /* MembraneRTC in Frameworks */ = {isa = PBXBuildFile; productRef = 44788B4F2A27A13100C43DD4 /* MembraneRTC */; }; 44ACD3EF293FC0D1001197EC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 44ACD3EE293FC0D1001197EC /* Debug.xcconfig */; }; 44ACD3F1293FCFA9001197EC /* Release.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 44ACD3F0293FCFA9001197EC /* Release.xcconfig */; }; 44C0FE9A291595C700E61E9A /* PeerConnectionManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44C0FE99291595C700E61E9A /* PeerConnectionManagerTest.swift */; }; @@ -71,7 +71,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 3B01482C27BA415D00907A8B /* MembraneRTC */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = MembraneRTC; sourceTree = ""; }; 3B1642DA27A134C4008BBBA7 /* RoomController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomController.swift; sourceTree = ""; }; 3B16A1BF2796C42B0095941F /* RoomView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RoomView.swift; sourceTree = ""; }; 3B16A1C02796C42B0095941F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -96,6 +95,8 @@ 3BCCBEBB2795619500A0AD4C /* MembraneVideoroomDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MembraneVideoroomDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3BD7249227AAD3DE00AFE9D9 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = ""; }; 3BDAC1DF27A2FCE200A2BB0D /* ParticipantVideoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipantVideoView.swift; sourceTree = ""; }; + 446D54342A279B9E00960E30 /* MembraneRTC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MembraneRTC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 446D54382A279BA600960E30 /* MembraneRTC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MembraneRTC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44ACD3EE293FC0D1001197EC /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; 44ACD3F0293FCFA9001197EC /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 44C0FE97291595C700E61E9A /* MembraneRTCTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MembraneRTCTest.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -110,7 +111,7 @@ 3BA235DB27AC1F600070031E /* FBLPromises in Frameworks */, 3B601BF027ABD2FE00668122 /* ReplayKit.framework in Frameworks */, 3BA235D727AC10C10070031E /* SwiftProtobuf in Frameworks */, - 3B0148B927BA4F6A00907A8B /* MembraneRTC in Frameworks */, + 44788B502A27A13100C43DD4 /* MembraneRTC in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -118,8 +119,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 44788B4E2A27A12C00C43DD4 /* MembraneRTC in Frameworks */, 3BCCBEF627956E1500A0AD4C /* Logging in Frameworks */, - 3B0148BB27BA4F7300907A8B /* MembraneRTC in Frameworks */, 3B04D3942798190F00E2B755 /* SwiftPhoenixClient in Frameworks */, 3B601C0127ABF88A00668122 /* SwiftProtobuf in Frameworks */, 3BCCBEF92795701600A0AD4C /* Promises in Frameworks */, @@ -136,13 +137,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 3B0148B327BA47C800907A8B /* Packages */ = { - isa = PBXGroup; - children = ( - ); - name = Packages; - sourceTree = ""; - }; 3B16A1BE2796C42B0095941F /* MembraneVideoroomDemo */ = { isa = PBXGroup; children = ( @@ -202,6 +196,8 @@ 3B601BEE27ABD2FE00668122 /* Frameworks */ = { isa = PBXGroup; children = ( + 446D54382A279BA600960E30 /* MembraneRTC.framework */, + 446D54342A279B9E00960E30 /* MembraneRTC.framework */, 3B601BEF27ABD2FE00668122 /* ReplayKit.framework */, ); name = Frameworks; @@ -230,8 +226,6 @@ 44ACD3F0293FCFA9001197EC /* Release.xcconfig */, 44ACD3EE293FC0D1001197EC /* Debug.xcconfig */, 3BB35DA627D61A7100892A6E /* README.md */, - 3B0148B327BA47C800907A8B /* Packages */, - 3B01482C27BA415D00907A8B /* MembraneRTC */, 3BA235D927AC156E0070031E /* MembraneVideoroomDemoScreensharingDebug.entitlements */, 3B16A1BE2796C42B0095941F /* MembraneVideoroomDemo */, 3B601BF127ABD2FE00668122 /* ScreenBroadcastExt */, @@ -278,7 +272,7 @@ packageProductDependencies = ( 3BA235D627AC10C10070031E /* SwiftProtobuf */, 3BA235DA27AC1F600070031E /* FBLPromises */, - 3B0148B827BA4F6A00907A8B /* MembraneRTC */, + 44788B4F2A27A13100C43DD4 /* MembraneRTC */, ); productName = MembraneVideoroomDemoScreensharing; productReference = 3B601BED27ABD2FE00668122 /* ScreenBroadcastExt.appex */; @@ -305,7 +299,7 @@ 3BCCBEF82795701600A0AD4C /* Promises */, 3B04D3932798190F00E2B755 /* SwiftPhoenixClient */, 3B601C0027ABF88A00668122 /* SwiftProtobuf */, - 3B0148BA27BA4F7300907A8B /* MembraneRTC */, + 44788B4D2A27A12C00C43DD4 /* MembraneRTC */, ); productName = MembraneVideoroomDemo; productReference = 3BCCBEBB2795619500A0AD4C /* MembraneVideoroomDemo.app */; @@ -836,14 +830,6 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 3B0148B827BA4F6A00907A8B /* MembraneRTC */ = { - isa = XCSwiftPackageProductDependency; - productName = MembraneRTC; - }; - 3B0148BA27BA4F7300907A8B /* MembraneRTC */ = { - isa = XCSwiftPackageProductDependency; - productName = MembraneRTC; - }; 3B04D3932798190F00E2B755 /* SwiftPhoenixClient */ = { isa = XCSwiftPackageProductDependency; package = 3B04D3922798190F00E2B755 /* XCRemoteSwiftPackageReference "SwiftPhoenixClient" */; @@ -874,6 +860,14 @@ package = 3BCCBEF72795701600A0AD4C /* XCRemoteSwiftPackageReference "promises" */; productName = Promises; }; + 44788B4D2A27A12C00C43DD4 /* MembraneRTC */ = { + isa = XCSwiftPackageProductDependency; + productName = MembraneRTC; + }; + 44788B4F2A27A13100C43DD4 /* MembraneRTC */ = { + isa = XCSwiftPackageProductDependency; + productName = MembraneRTC; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 3BCCBEB32795619500A0AD4C /* Project object */; diff --git a/MembraneVideoroomDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MembraneVideoroomDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7d3d08b3..7379945f 100644 --- a/MembraneVideoroomDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MembraneVideoroomDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,88 +1,68 @@ { - "object": { - "pins": [ - { - "package": "Promises", - "repositoryURL": "https://github.com/google/promises.git", - "state": { - "branch": null, - "revision": "611337c330350c9c1823ad6d671e7f936af5ee13", - "version": "2.0.0" - } - }, - { - "package": "RxSwift", - "repositoryURL": "https://github.com/ReactiveX/RxSwift.git", - "state": { - "branch": null, - "revision": "b4307ba0b6425c0ba4178e138799946c3da594f8", - "version": "6.5.0" - } - }, - { - "package": "WebRTC", - "repositoryURL": "https://github.com/webrtc-sdk/Specs.git", - "state": { - "branch": null, - "revision": "80c9eebccf89fb877e44b5f942cb9d2024fa7b86", - "version": "93.4577.1" - } - }, - { - "package": "Starscream", - "repositoryURL": "https://github.com/daltoniam/Starscream.git", - "state": { - "branch": null, - "revision": "e6b65c6d9077ea48b4a7bdda8994a1d3c6969c8d", - "version": "3.1.1" - } - }, - { - "package": "swift-collections", - "repositoryURL": "https://github.com/apple/swift-collections.git", - "state": { - "branch": null, - "revision": "48254824bb4248676bf7ce56014ff57b142b77eb", - "version": "1.0.2" - } - }, - { - "package": "swift-log", - "repositoryURL": "https://github.com/apple/swift-log.git", - "state": { - "branch": null, - "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", - "version": "1.4.2" - } - }, - { - "package": "swift-nio-zlib-support", - "repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git", - "state": { - "branch": null, - "revision": "37760e9a52030bb9011972c5213c3350fa9d41fd", - "version": "1.0.0" - } - }, - { - "package": "SwiftProtobuf", - "repositoryURL": "https://github.com/apple/swift-protobuf.git", - "state": { - "branch": null, - "revision": "7e2c5f3cbbeea68e004915e3a8961e20bd11d824", - "version": "1.18.0" - } - }, - { - "package": "SwiftPhoenixClient", - "repositoryURL": "https://github.com/davidstump/SwiftPhoenixClient.git", - "state": { - "branch": null, - "revision": "882231977f6381827ad564ccaff622de2d550477", - "version": "4.0.0" - } + "pins" : [ + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "611337c330350c9c1823ad6d671e7f936af5ee13", + "version" : "2.0.0" } - ] - }, - "version": 1 + }, + { + "identity" : "rxswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveX/RxSwift.git", + "state" : { + "revision" : "b4307ba0b6425c0ba4178e138799946c3da594f8", + "version" : "6.5.0" + } + }, + { + "identity" : "starscream", + "kind" : "remoteSourceControl", + "location" : "https://github.com/daltoniam/Starscream.git", + "state" : { + "revision" : "e6b65c6d9077ea48b4a7bdda8994a1d3c6969c8d", + "version" : "3.1.1" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", + "version" : "1.4.2" + } + }, + { + "identity" : "swift-nio-zlib-support", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-zlib-support.git", + "state" : { + "revision" : "37760e9a52030bb9011972c5213c3350fa9d41fd", + "version" : "1.0.0" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "7e2c5f3cbbeea68e004915e3a8961e20bd11d824", + "version" : "1.18.0" + } + }, + { + "identity" : "swiftphoenixclient", + "kind" : "remoteSourceControl", + "location" : "https://github.com/davidstump/SwiftPhoenixClient.git", + "state" : { + "revision" : "882231977f6381827ad564ccaff622de2d550477", + "version" : "4.0.0" + } + } + ], + "version" : 2 } diff --git a/MembraneVideoroomDemo.xcworkspace/contents.xcworkspacedata b/MembraneVideoroomDemo.xcworkspace/contents.xcworkspacedata index 03f76242..297f4daa 100644 --- a/MembraneVideoroomDemo.xcworkspace/contents.xcworkspacedata +++ b/MembraneVideoroomDemo.xcworkspace/contents.xcworkspacedata @@ -1,6 +1,9 @@ + + diff --git a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6b4b6052..32e5b36a 100644 --- a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/ReactiveX/RxSwift.git", "state": { "branch": null, - "revision": "b4307ba0b6425c0ba4178e138799946c3da594f8", - "version": "6.5.0" + "revision": "9dcaa4b333db437b0fbfaf453fad29069044a8b4", + "version": "6.6.0" } }, { @@ -46,6 +46,24 @@ "version": "1.0.4" } }, + { + "package": "SwiftDocCPlugin", + "repositoryURL": "https://github.com/apple/swift-docc-plugin", + "state": { + "branch": null, + "revision": "9b1258905c21fc1b97bf03d1b4ca12c4ec4e5fda", + "version": "1.2.0" + } + }, + { + "package": "SymbolKit", + "repositoryURL": "https://github.com/apple/swift-docc-symbolkit", + "state": { + "branch": null, + "revision": "b45d1f2ed151d057b54504d653e0da5552844e34", + "version": "1.0.0" + } + }, { "package": "swift-log", "repositoryURL": "https://github.com/apple/swift-log.git", diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 00000000..32e5b36a --- /dev/null +++ b/Package.resolved @@ -0,0 +1,97 @@ +{ + "object": { + "pins": [ + { + "package": "Promises", + "repositoryURL": "https://github.com/google/promises.git", + "state": { + "branch": null, + "revision": "ec957ccddbcc710ccc64c9dcbd4c7006fcf8b73a", + "version": "2.2.0" + } + }, + { + "package": "RxSwift", + "repositoryURL": "https://github.com/ReactiveX/RxSwift.git", + "state": { + "branch": null, + "revision": "9dcaa4b333db437b0fbfaf453fad29069044a8b4", + "version": "6.6.0" + } + }, + { + "package": "WebRTC", + "repositoryURL": "https://github.com/webrtc-sdk/Specs.git", + "state": { + "branch": null, + "revision": "aaef003e42a5ec34c3ff44abc6c352d18e39a278", + "version": "104.5112.15" + } + }, + { + "package": "Starscream", + "repositoryURL": "https://github.com/daltoniam/Starscream.git", + "state": { + "branch": null, + "revision": "a063fda2b8145a231953c20e7a646be254365396", + "version": "3.1.2" + } + }, + { + "package": "swift-collections", + "repositoryURL": "https://github.com/apple/swift-collections.git", + "state": { + "branch": null, + "revision": "937e904258d22af6e447a0b72c0bc67583ef64a2", + "version": "1.0.4" + } + }, + { + "package": "SwiftDocCPlugin", + "repositoryURL": "https://github.com/apple/swift-docc-plugin", + "state": { + "branch": null, + "revision": "9b1258905c21fc1b97bf03d1b4ca12c4ec4e5fda", + "version": "1.2.0" + } + }, + { + "package": "SymbolKit", + "repositoryURL": "https://github.com/apple/swift-docc-symbolkit", + "state": { + "branch": null, + "revision": "b45d1f2ed151d057b54504d653e0da5552844e34", + "version": "1.0.0" + } + }, + { + "package": "swift-log", + "repositoryURL": "https://github.com/apple/swift-log.git", + "state": { + "branch": null, + "revision": "32e8d724467f8fe623624570367e3d50c5638e46", + "version": "1.5.2" + } + }, + { + "package": "SwiftProtobuf", + "repositoryURL": "https://github.com/apple/swift-protobuf.git", + "state": { + "branch": null, + "revision": "0af9125c4eae12a4973fb66574c53a54962a9e1e", + "version": "1.21.0" + } + }, + { + "package": "SwiftPhoenixClient", + "repositoryURL": "https://github.com/davidstump/SwiftPhoenixClient.git", + "state": { + "branch": null, + "revision": "882231977f6381827ad564ccaff622de2d550477", + "version": "4.0.0" + } + } + ] + }, + "version": 1 +} diff --git a/MembraneRTC/Package.swift b/Package.swift similarity index 95% rename from MembraneRTC/Package.swift rename to Package.swift index a394665a..34ffdca8 100644 --- a/MembraneRTC/Package.swift +++ b/Package.swift @@ -28,6 +28,7 @@ let package = Package( .upToNextMajor(from: "4.0.0")), .package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.4.2")), .package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.1")), + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/MembraneRTC/Sources/Documentation.docc/MembraneRTC.md b/Sources/Documentation.docc/MembraneRTC.md similarity index 100% rename from MembraneRTC/Sources/Documentation.docc/MembraneRTC.md rename to Sources/Documentation.docc/MembraneRTC.md diff --git a/MembraneRTC/Sources/MembraneRTC/Constants.swift b/Sources/MembraneRTC/Constants.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Constants.swift rename to Sources/MembraneRTC/Constants.swift diff --git a/MembraneRTC/Sources/MembraneRTC/EventTransport/EventTransport.swift b/Sources/MembraneRTC/EventTransport/EventTransport.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/EventTransport/EventTransport.swift rename to Sources/MembraneRTC/EventTransport/EventTransport.swift diff --git a/MembraneRTC/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift b/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/EventTransport/PhoenixTransport.swift rename to Sources/MembraneRTC/EventTransport/PhoenixTransport.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Events/Event.swift b/Sources/MembraneRTC/Events/Event.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Events/Event.swift rename to Sources/MembraneRTC/Events/Event.swift diff --git a/MembraneRTC/Sources/MembraneRTC/IPC/IPC.swift b/Sources/MembraneRTC/IPC/IPC.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/IPC/IPC.swift rename to Sources/MembraneRTC/IPC/IPC.swift diff --git a/MembraneRTC/Sources/MembraneRTC/IPC/broadcast_ipc.pb.swift b/Sources/MembraneRTC/IPC/broadcast_ipc.pb.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/IPC/broadcast_ipc.pb.swift rename to Sources/MembraneRTC/IPC/broadcast_ipc.pb.swift diff --git a/MembraneRTC/Sources/MembraneRTC/IPC/broadcast_ipc.proto b/Sources/MembraneRTC/IPC/broadcast_ipc.proto similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/IPC/broadcast_ipc.proto rename to Sources/MembraneRTC/IPC/broadcast_ipc.proto diff --git a/MembraneRTC/Sources/MembraneRTC/Media/BroadcastSampleSource.swift b/Sources/MembraneRTC/Media/BroadcastSampleSource.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/BroadcastSampleSource.swift rename to Sources/MembraneRTC/Media/BroadcastSampleSource.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Capturers/CameraCapturer.swift b/Sources/MembraneRTC/Media/Capturers/CameraCapturer.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Capturers/CameraCapturer.swift rename to Sources/MembraneRTC/Media/Capturers/CameraCapturer.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Capturers/FileCapturer.swift b/Sources/MembraneRTC/Media/Capturers/FileCapturer.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Capturers/FileCapturer.swift rename to Sources/MembraneRTC/Media/Capturers/FileCapturer.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift b/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift rename to Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Capturers/ScreenCapturer.swift b/Sources/MembraneRTC/Media/Capturers/ScreenCapturer.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Capturers/ScreenCapturer.swift rename to Sources/MembraneRTC/Media/Capturers/ScreenCapturer.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Capturers/VideoCapturer.swift b/Sources/MembraneRTC/Media/Capturers/VideoCapturer.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Capturers/VideoCapturer.swift rename to Sources/MembraneRTC/Media/Capturers/VideoCapturer.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Dimensions.swift b/Sources/MembraneRTC/Media/Dimensions.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Dimensions.swift rename to Sources/MembraneRTC/Media/Dimensions.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/ScreenBroadcastNotificationReceiver.swift b/Sources/MembraneRTC/Media/ScreenBroadcastNotificationReceiver.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/ScreenBroadcastNotificationReceiver.swift rename to Sources/MembraneRTC/Media/ScreenBroadcastNotificationReceiver.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/AudioTrack.swift b/Sources/MembraneRTC/Media/Tracks/AudioTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/AudioTrack.swift rename to Sources/MembraneRTC/Media/Tracks/AudioTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalAudioTrack.swift b/Sources/MembraneRTC/Media/Tracks/LocalAudioTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalAudioTrack.swift rename to Sources/MembraneRTC/Media/Tracks/LocalAudioTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalScreenBroadcastTrack.swift b/Sources/MembraneRTC/Media/Tracks/LocalScreenBroadcastTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalScreenBroadcastTrack.swift rename to Sources/MembraneRTC/Media/Tracks/LocalScreenBroadcastTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalTrack.swift b/Sources/MembraneRTC/Media/Tracks/LocalTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalTrack.swift rename to Sources/MembraneRTC/Media/Tracks/LocalTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalVideoTrack.swift b/Sources/MembraneRTC/Media/Tracks/LocalVideoTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/LocalVideoTrack.swift rename to Sources/MembraneRTC/Media/Tracks/LocalVideoTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/MediaTrackProvider.swift b/Sources/MembraneRTC/Media/Tracks/MediaTrackProvider.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/MediaTrackProvider.swift rename to Sources/MembraneRTC/Media/Tracks/MediaTrackProvider.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/RemoteAudioTrack.swift b/Sources/MembraneRTC/Media/Tracks/RemoteAudioTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/RemoteAudioTrack.swift rename to Sources/MembraneRTC/Media/Tracks/RemoteAudioTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/RemoteTrack.swift b/Sources/MembraneRTC/Media/Tracks/RemoteTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/RemoteTrack.swift rename to Sources/MembraneRTC/Media/Tracks/RemoteTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/RemoteVideoTrack.swift b/Sources/MembraneRTC/Media/Tracks/RemoteVideoTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/RemoteVideoTrack.swift rename to Sources/MembraneRTC/Media/Tracks/RemoteVideoTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/Tracks/VideoTrack.swift b/Sources/MembraneRTC/Media/Tracks/VideoTrack.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/Tracks/VideoTrack.swift rename to Sources/MembraneRTC/Media/Tracks/VideoTrack.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Media/VideoParameters.swift b/Sources/MembraneRTC/Media/VideoParameters.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Media/VideoParameters.swift rename to Sources/MembraneRTC/Media/VideoParameters.swift diff --git a/MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift b/Sources/MembraneRTC/MembraneRTC.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/MembraneRTC.swift rename to Sources/MembraneRTC/MembraneRTC.swift diff --git a/MembraneRTC/Sources/MembraneRTC/MembraneRTCDelegate.swift b/Sources/MembraneRTC/MembraneRTCDelegate.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/MembraneRTCDelegate.swift rename to Sources/MembraneRTC/MembraneRTCDelegate.swift diff --git a/MembraneRTC/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift b/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift rename to Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift diff --git a/MembraneRTC/Sources/MembraneRTC/PeerConnectionListener.swift b/Sources/MembraneRTC/PeerConnectionListener.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/PeerConnectionListener.swift rename to Sources/MembraneRTC/PeerConnectionListener.swift diff --git a/MembraneRTC/Sources/MembraneRTC/PeerConnectionManager.swift b/Sources/MembraneRTC/PeerConnectionManager.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/PeerConnectionManager.swift rename to Sources/MembraneRTC/PeerConnectionManager.swift diff --git a/MembraneRTC/Sources/MembraneRTC/RTCEngineCommunication.swift b/Sources/MembraneRTC/RTCEngineCommunication.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/RTCEngineCommunication.swift rename to Sources/MembraneRTC/RTCEngineCommunication.swift diff --git a/MembraneRTC/Sources/MembraneRTC/RTCEngineListener.swift b/Sources/MembraneRTC/RTCEngineListener.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/RTCEngineListener.swift rename to Sources/MembraneRTC/RTCEngineListener.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/AnyJson.swift b/Sources/MembraneRTC/Types/AnyJson.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/AnyJson.swift rename to Sources/MembraneRTC/Types/AnyJson.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/Encoder.swift b/Sources/MembraneRTC/Types/Encoder.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/Encoder.swift rename to Sources/MembraneRTC/Types/Encoder.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/EncodingReason.swift b/Sources/MembraneRTC/Types/EncodingReason.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/EncodingReason.swift rename to Sources/MembraneRTC/Types/EncodingReason.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/Metadata.swift b/Sources/MembraneRTC/Types/Metadata.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/Metadata.swift rename to Sources/MembraneRTC/Types/Metadata.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/Peer.swift b/Sources/MembraneRTC/Types/Peer.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/Peer.swift rename to Sources/MembraneRTC/Types/Peer.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/RTCStats.swift b/Sources/MembraneRTC/Types/RTCStats.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/RTCStats.swift rename to Sources/MembraneRTC/Types/RTCStats.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/SerializedMediaEvent.swift b/Sources/MembraneRTC/Types/SerializedMediaEvent.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/SerializedMediaEvent.swift rename to Sources/MembraneRTC/Types/SerializedMediaEvent.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/SimulcastConfig.swift b/Sources/MembraneRTC/Types/SimulcastConfig.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/SimulcastConfig.swift rename to Sources/MembraneRTC/Types/SimulcastConfig.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/TrackBandwidthLimit.swift b/Sources/MembraneRTC/Types/TrackBandwidthLimit.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/TrackBandwidthLimit.swift rename to Sources/MembraneRTC/Types/TrackBandwidthLimit.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/TrackContext.swift b/Sources/MembraneRTC/Types/TrackContext.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/TrackContext.swift rename to Sources/MembraneRTC/Types/TrackContext.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Types/VadStatus.swift b/Sources/MembraneRTC/Types/VadStatus.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Types/VadStatus.swift rename to Sources/MembraneRTC/Types/VadStatus.swift diff --git a/MembraneRTC/Sources/MembraneRTC/UI/SwiftUIVideoView.swift b/Sources/MembraneRTC/UI/SwiftUIVideoView.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/UI/SwiftUIVideoView.swift rename to Sources/MembraneRTC/UI/SwiftUIVideoView.swift diff --git a/MembraneRTC/Sources/MembraneRTC/UI/VideoView.swift b/Sources/MembraneRTC/UI/VideoView.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/UI/VideoView.swift rename to Sources/MembraneRTC/UI/VideoView.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Utilities/MulticastDelegate.swift b/Sources/MembraneRTC/Utilities/MulticastDelegate.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Utilities/MulticastDelegate.swift rename to Sources/MembraneRTC/Utilities/MulticastDelegate.swift diff --git a/MembraneRTC/Sources/MembraneRTC/Utilities/SimulcastUtils.swift b/Sources/MembraneRTC/Utilities/SimulcastUtils.swift similarity index 100% rename from MembraneRTC/Sources/MembraneRTC/Utilities/SimulcastUtils.swift rename to Sources/MembraneRTC/Utilities/SimulcastUtils.swift From 9e73bf1b86c36b68e19252eb7547659d36504904 Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Mon, 12 Jun 2023 13:08:00 +0200 Subject: [PATCH 3/8] [RTC-270] Remove peers (#38) * [RTC-270] Remove peers * Fix docs * Review comments * update packages * update packages --- .github/workflows/publish_docs.yaml | 2 + .release-it.json | 4 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- MembraneVideoroomDemo/Controllers/App.swift | 10 +- .../Controllers/RoomController.swift | 64 ++++---- Package.resolved | 4 +- Sources/MembraneRTC/Events/Event.swift | 87 +++++------ Sources/MembraneRTC/MembraneRTC.swift | 144 ++++++++---------- Sources/MembraneRTC/MembraneRTCDelegate.swift | 33 ++-- .../MembraneRTC/PeerConnectionManager.swift | 2 +- .../MembraneRTC/RTCEngineCommunication.swift | 48 +++--- Sources/MembraneRTC/RTCEngineListener.swift | 19 ++- .../Types/{Peer.swift => Endpoint.swift} | 18 ++- Sources/MembraneRTC/Types/TrackContext.swift | 6 +- 14 files changed, 204 insertions(+), 241 deletions(-) rename Sources/MembraneRTC/Types/{Peer.swift => Endpoint.swift} (63%) diff --git a/.github/workflows/publish_docs.yaml b/.github/workflows/publish_docs.yaml index 367c3e4e..65f5e5f2 100644 --- a/.github/workflows/publish_docs.yaml +++ b/.github/workflows/publish_docs.yaml @@ -2,6 +2,8 @@ name: Deploy Docs on: push: + tags: + - "*" jobs: build: diff --git a/.release-it.json b/.release-it.json index a7e4e0c9..983272a3 100644 --- a/.release-it.json +++ b/.release-it.json @@ -6,8 +6,8 @@ } }, "hooks": { - "after:bump": "pod lib lint --allow-warnings", - "before:github:release": "pod trunk push --allow-warnings" + "after:bump": "pod lib lint", + "before:github:release": "pod trunk push" }, "github": { "release": true diff --git a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved index 32e5b36a..ef110cdc 100644 --- a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/apple/swift-protobuf.git", "state": { "branch": null, - "revision": "0af9125c4eae12a4973fb66574c53a54962a9e1e", - "version": "1.21.0" + "revision": "f25867a208f459d3c5a06935dceb9083b11cd539", + "version": "1.22.0" } }, { diff --git a/MembraneVideoroomDemo/Controllers/App.swift b/MembraneVideoroomDemo/Controllers/App.swift index 93bdf799..8f0d433b 100644 --- a/MembraneVideoroomDemo/Controllers/App.swift +++ b/MembraneVideoroomDemo/Controllers/App.swift @@ -84,9 +84,9 @@ extension AppController: MembraneRTCDelegate { transport?.send(event: event) } - func onJoinSuccess(peerID _: String, peersInRoom _: [Peer]) {} + func onConnected(endpointId _: String, otherEndpoints _: [Endpoint]) {} - func onJoinError(metadata _: Any) {} + func onConnectionError(metadata _: Any) {} func onTrackReady(ctx _: TrackContext) {} @@ -96,11 +96,11 @@ extension AppController: MembraneRTCDelegate { func onTrackUpdated(ctx _: TrackContext) {} - func onPeerJoined(peer _: Peer) {} + func onEndpointAdded(endpoint _: Endpoint) {} - func onPeerLeft(peer _: Peer) {} + func onEndpointRemoved(endpoint _: Endpoint) {} - func onPeerUpdated(peer _: Peer) {} + func onEndpointUpdated(endpoint _: Endpoint) {} } extension AppController: PhoenixTransportDelegate { diff --git a/MembraneVideoroomDemo/Controllers/RoomController.swift b/MembraneVideoroomDemo/Controllers/RoomController.swift index 05c3ecf8..3606c5f3 100644 --- a/MembraneVideoroomDemo/Controllers/RoomController.swift +++ b/MembraneVideoroomDemo/Controllers/RoomController.swift @@ -88,7 +88,7 @@ class RoomController: ObservableObject { room.add(delegate: self) - self.room?.join(peerMetadata: .init(["displayName": displayName])) + self.room?.connect(metadata: .init(["displayName": displayName])) } func enableTrack(_ type: LocalTrackType, enabled: Bool) { @@ -174,7 +174,7 @@ class RoomController: ObservableObject { return } - let displayName = room.currentPeer().metadata["displayName"] ?? "UNKNOWN" + let displayName = room.currentEndpoint().metadata["displayName"] ?? "UNKNOWN" let preset = VideoParameters.presetScreenShareHD15 let videoParameters = VideoParameters( @@ -324,14 +324,15 @@ extension RoomController: MembraneRTCDelegate { func onSendMediaEvent(event: SerializedMediaEvent) {} - func onJoinSuccess(peerID: String, peersInRoom: [Peer]) { - localParticipantId = peerID + func onConnected(endpointId: String, otherEndpoints: [Endpoint]) { + localParticipantId = endpointId - let localParticipant = Participant(id: peerID, displayName: "Me", isAudioTrackActive: true) + let localParticipant = Participant(id: endpointId, displayName: "Me", isAudioTrackActive: true) - let participants = peersInRoom.map { peer in + let participants = otherEndpoints.map { endpoint in Participant( - id: peer.id, displayName: peer.metadata["displayName"] as? String ?? "", isAudioTrackActive: false) + id: endpoint.id, displayName: endpoint.metadata["displayName"] as? String ?? "", + isAudioTrackActive: false) } DispatchQueue.main.async { @@ -351,34 +352,35 @@ extension RoomController: MembraneRTCDelegate { } } - func onJoinError(metadata _: Any) { - errorMessage = "Failed to join a room" + func onConnectionError(metadata _: Any) { + errorMessage = "Failed to connect" } func onTrackReady(ctx: TrackContext) { ctx.setOnVoiceActivityChangedListener { trackContext in - if let participantVideo = self.participantVideos.first(where: { $0.participant.id == trackContext.peer.id }) - { + if let participantVideo = self.participantVideos.first(where: { + $0.participant.id == trackContext.endpoint.id + }) { DispatchQueue.main.async { participantVideo.vadStatus = trackContext.vadStatus } } - if self.primaryVideo?.participant.id == trackContext.peer.id { + if self.primaryVideo?.participant.id == trackContext.endpoint.id { DispatchQueue.main.async { self.primaryVideo?.vadStatus = trackContext.vadStatus } } } - guard var participant = participants[ctx.peer.id] else { + guard var participant = participants[ctx.endpoint.id] else { return } guard let videoTrack = ctx.track as? VideoTrack else { DispatchQueue.main.async { participant.isAudioTrackActive = ctx.metadata["active"] as? Bool == true - self.participants[ctx.peer.id] = participant - let pv = self.findParticipantVideoByOwner(participantId: ctx.peer.id) + self.participants[ctx.endpoint.id] = participant + let pv = self.findParticipantVideoByOwner(participantId: ctx.endpoint.id) pv?.participant = participant } @@ -401,7 +403,7 @@ extension RoomController: MembraneRTCDelegate { id: ctx.trackId, participant: participant, videoTrack: videoTrack, isScreensharing: isScreensharing, isActive: ctx.metadata["active"] as? Bool == true || isScreensharing) - guard let existingVideo = self.findParticipantVideoByOwner(participantId: ctx.peer.id) else { + guard let existingVideo = self.findParticipantVideoByOwner(participantId: ctx.endpoint.id) else { add(video: video) if isScreensharing { @@ -449,50 +451,50 @@ extension RoomController: MembraneRTCDelegate { if ctx.metadata["type"] as? String == "camera" { DispatchQueue.main.async { - if ctx.peer.id == self.primaryVideo?.participant.id { + if ctx.endpoint.id == self.primaryVideo?.participant.id { self.primaryVideo?.isActive = isActive } else { - self.participantVideos.first(where: { $0.participant.id == ctx.peer.id })?.isActive = + self.participantVideos.first(where: { $0.participant.id == ctx.endpoint.id })?.isActive = isActive } } } else { DispatchQueue.main.async { - guard var p = self.participants[ctx.peer.id] else { + guard var p = self.participants[ctx.endpoint.id] else { return } p.isAudioTrackActive = isActive - self.participants[ctx.peer.id] = p - if ctx.peer.id == self.primaryVideo?.participant.id { + self.participants[ctx.endpoint.id] = p + if ctx.endpoint.id == self.primaryVideo?.participant.id { self.primaryVideo?.participant = p } else { - self.participantVideos.first(where: { $0.participant.id == ctx.peer.id })?.participant = p + self.participantVideos.first(where: { $0.participant.id == ctx.endpoint.id })?.participant = p } } } } - func onPeerJoined(peer: Peer) { - self.participants[peer.id] = Participant( - id: peer.id, displayName: peer.metadata["displayName"] as? String ?? "", isAudioTrackActive: false) + func onEndpointAdded(endpoint: Endpoint) { + self.participants[endpoint.id] = Participant( + id: endpoint.id, displayName: endpoint.metadata["displayName"] as? String ?? "", isAudioTrackActive: false) let pv = - ParticipantVideo(id: peer.id, participant: participants[peer.id]!, videoTrack: nil, isActive: false) + ParticipantVideo(id: endpoint.id, participant: participants[endpoint.id]!, videoTrack: nil, isActive: false) add(video: pv) } - func onPeerLeft(peer: Peer) { + func onEndpointRemoved(endpoint: Endpoint) { DispatchQueue.main.async { - self.participants.removeValue(forKey: peer.id) - self.participantVideos = self.participantVideos.filter({ $0.participant.id != peer.id }) - if self.primaryVideo?.participant.id == peer.id { + self.participants.removeValue(forKey: endpoint.id) + self.participantVideos = self.participantVideos.filter({ $0.participant.id != endpoint.id }) + if self.primaryVideo?.participant.id == endpoint.id { self.primaryVideo = nil } } } - func onPeerUpdated(peer _: Peer) {} + func onEndpointUpdated(endpoint _: Endpoint) {} private func toggleTrackEncoding( simulcastConfig: SimulcastConfig, trackId: String, encoding: TrackEncoding diff --git a/Package.resolved b/Package.resolved index 32e5b36a..ef110cdc 100644 --- a/Package.resolved +++ b/Package.resolved @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/apple/swift-protobuf.git", "state": { "branch": null, - "revision": "0af9125c4eae12a4973fb66574c53a54962a9e1e", - "version": "1.21.0" + "revision": "f25867a208f459d3c5a06935dceb9083b11cd539", + "version": "1.22.0" } }, { diff --git a/Sources/MembraneRTC/Events/Event.swift b/Sources/MembraneRTC/Events/Event.swift index 50362e02..b439c3f4 100644 --- a/Sources/MembraneRTC/Events/Event.swift +++ b/Sources/MembraneRTC/Events/Event.swift @@ -9,11 +9,10 @@ public protocol SendableEvent { /// Available types of incoming media events. public enum ReceivableEventType: String, Codable { - case PeerAccepted = "peerAccepted" - case PeerJoined = "peerJoined" - case PeerLeft = "peerLeft" - case PeerUpdated = "peerUpdated" - case PeerRemoved = "peerRemoved" + case Connected = "connected" + case EndpointAdded = "endpointAdded" + case EndpointRemoved = "endpointRemoved" + case EndpointUpdated = "endpointUpdated" case Custom = "custom" case OfferData = "offerData" case Candidate = "candidate" @@ -86,23 +85,23 @@ public enum Events { } switch base.type { - case .PeerAccepted: - let event: PeerAcceptedEvent? = decodeEvent(from: data) + case .Connected: + let event: ConnectedEvent? = decodeEvent(from: data) return event - case .PeerJoined: - let event: PeerJoinedEvent? = decodeEvent(from: data) + case .EndpointAdded: + let event: EndpointAddedEvent? = decodeEvent(from: data) return event - case .PeerLeft: - let event: PeerLeftEvent? = decodeEvent(from: data) + case .EndpointRemoved: + let event: EndpointRemovedEvent? = decodeEvent(from: data) return event - case .PeerUpdated: - let event: PeerUpdateEvent? = decodeEvent(from: data) + case .EndpointUpdated: + let event: EndpointUpdatedEvent? = decodeEvent(from: data) return event @@ -155,13 +154,6 @@ public enum Events { return event.data - case .PeerRemoved: - guard let event: CustomEvent = decodeEvent(from: data) else { - return nil - } - - return event.data - case .VadNotification: guard let event: CustomEvent = decodeEvent(from: data) else { return nil @@ -190,12 +182,12 @@ public enum Events { /* Sendable events */ -struct JoinEvent: SendableEvent { +struct ConnectEvent: SendableEvent { let metadata: Metadata func serialize() -> Payload { return .init([ - "type": "join", + "type": "connect", "data": ["metadata": metadata], ]) } @@ -218,8 +210,8 @@ struct SdpOfferEvent: SendableEvent { ], "trackIdToTrackMetadata": trackIdToTrackMetadata, "midToTrackId": midToTrackId, - ], - ], + ] as [String: Any], + ] as [String: Any], ]) } } @@ -236,8 +228,8 @@ struct LocalCandidateEvent: SendableEvent { "data": [ "candidate": candidate, "sdpMLineIndex": sdpMLineIndex, - ], - ], + ] as [String: Any], + ] as [String: Any], ]) } } @@ -266,12 +258,12 @@ struct SelectEncodingEvent: SendableEvent { "trackId": trackId, "variant": encoding, ], - ], + ] as [String: Any], ]) } } -struct UpdatePeerMetadata: SendableEvent { +struct UpdateEndpointMetadata: SendableEvent { let metadata: Metadata func serialize() -> Payload { @@ -289,7 +281,7 @@ struct UpdateTrackMetadata: SendableEvent { func serialize() -> Payload { return .init([ "type": "updateTrackMetadata", - "data": ["trackId": trackId, "trackMetadata": trackMetadata], + "data": ["trackId": trackId, "trackMetadata": trackMetadata] as [String: Any], ]) } } @@ -298,37 +290,40 @@ struct UpdateTrackMetadata: SendableEvent { Receivable events */ -struct PeerAcceptedEvent: ReceivableEvent, Codable { +struct ConnectedEvent: ReceivableEvent, Codable { struct Data: Codable { let id: String - let peersInRoom: [Peer] + let otherEndpoints: [Endpoint] } let type: ReceivableEventType let data: Data } -struct PeerJoinedEvent: ReceivableEvent, Codable { +struct EndpointAddedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peer: Peer + let id: String + let type: String + let metadata: Metadata + let trackIdToMetadata: [String: Metadata]? } let type: ReceivableEventType let data: Data } -struct PeerLeftEvent: ReceivableEvent, Codable { +struct EndpointRemovedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peerId: String + let id: String } let type: ReceivableEventType let data: Data } -struct PeerUpdateEvent: ReceivableEvent, Codable { +struct EndpointUpdatedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peerId: String + let endpointId: String let metadata: Metadata } @@ -336,16 +331,6 @@ struct PeerUpdateEvent: ReceivableEvent, Codable { let data: Data } -struct PeerRemovedEvent: ReceivableEvent, Codable { - struct Data: Codable { - let peerId: String - let reason: String - } - - let type: ReceivableEventType - let data: Data -} - struct OfferDataEvent: ReceivableEvent, Codable { struct TurnServer: Codable { let username: String @@ -366,7 +351,7 @@ struct OfferDataEvent: ReceivableEvent, Codable { struct TracksAddedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peerId: String + let endpointId: String let trackIdToMetadata: [String: Metadata] } @@ -376,7 +361,7 @@ struct TracksAddedEvent: ReceivableEvent, Codable { struct TracksRemovedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peerId: String + let endpointId: String let trackIds: [String] } @@ -386,7 +371,7 @@ struct TracksRemovedEvent: ReceivableEvent, Codable { struct TracksUpdatedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peerId: String + let endpointId: String let trackId: String let metadata: Metadata } @@ -419,7 +404,7 @@ struct RemoteCandidateEvent: ReceivableEvent, Codable { struct EncodingSwitchedEvent: ReceivableEvent, Codable { struct Data: Codable { - let peerId: String + let endpointId: String let trackId: String let encoding: String let reason: String diff --git a/Sources/MembraneRTC/MembraneRTC.swift b/Sources/MembraneRTC/MembraneRTC.swift index 369224ca..e5aa7211 100644 --- a/Sources/MembraneRTC/MembraneRTC.swift +++ b/Sources/MembraneRTC/MembraneRTC.swift @@ -22,14 +22,14 @@ internal let pcLogPrefix = "[PeerConnection]" /// /// It is recommended to request necessary audio and video tracks before joining the room but it does not mean it can't be done afterwards (in case of screencast) /// -/// Once the user created the MembraneRTC client and connected to the server transport layer they can call the `join` method to initialize joining the session. -/// After receiving `onJoinSuccess` a user will receive notification about various peers joining/leaving the session, new tracks being published and ready for playback +/// Once the user created the MembraneRTC client and connected to the server transport layer they can call the `connect` method to initialize joining the session. +/// After receiving `onConnected` a user will receive notification about various peers joining/leaving the session, new tracks being published and ready for playback /// or going inactive. public class MembraneRTC: MulticastDelegate, ObservableObject, RTCEngineListener, PeerConnectionListener { enum State { - case awaitingJoin + case awaitingConnect case connected case disconnected } @@ -58,10 +58,10 @@ public class MembraneRTC: MulticastDelegate, ObservableObje private var localTracks: [LocalTrack] = [] - private var localPeer = Peer(id: "", metadata: .init([:]), trackIdToMetadata: [:]) + private var localEndpoint = Endpoint(id: "", type: "webrtc", metadata: .init([:]), trackIdToMetadata: [:]) // mapping from peer's id to itself - private var remotePeers: [String: Peer] = [:] + private var remoteEndpoints: [String: Endpoint] = [:] // mapping from remote track's id to its context private var trackContexts: [String: TrackContext] = [:] @@ -79,7 +79,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje internal init(config: RTCConfiguration, encoder: Encoder) { sdkLogger.logLevel = .info - state = .awaitingJoin + state = .awaitingConnect self.config = config @@ -120,15 +120,15 @@ public class MembraneRTC: MulticastDelegate, ObservableObje /// Initiaites join process once the client has successfully connected. /// - /// Once completed either `onJoinSuccess` or `onJoinError` of client's delegate gets invovked. - public func join(peerMetadata: Metadata) { - guard state == .awaitingJoin else { + /// Once completed either `onConnected` or `onConnectError` of client's delegate gets invovked. + public func connect(metadata: Metadata) { + guard state == .awaitingConnect else { return } - localPeer = localPeer.with(metadata: peerMetadata) + localEndpoint = localEndpoint.with(metadata: metadata) - engineCommunication.join(peerMetadata: peerMetadata) + engineCommunication.connect(metadata: metadata) } /// Disconnects from the `Membrane RTC Engine` transport and closes the exisitng `RTCPeerConnection` @@ -183,7 +183,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje localTracks.append(videoTrack) - localPeer = localPeer.withTrack(trackId: videoTrack.rtcTrack().trackId, metadata: metadata) + localEndpoint = localEndpoint.withTrack(trackId: videoTrack.rtcTrack().trackId, metadata: metadata) if state == .connected { engineCommunication.renegotiateTracks() @@ -213,7 +213,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje localTracks.append(audioTrack) - localPeer = localPeer.withTrack(trackId: audioTrack.rtcTrack().trackId, metadata: metadata) + localEndpoint = localEndpoint.withTrack(trackId: audioTrack.rtcTrack().trackId, metadata: metadata) if state == .connected { engineCommunication.renegotiateTracks() @@ -291,16 +291,16 @@ public class MembraneRTC: MulticastDelegate, ObservableObje peerConnectionManager.removeTrack(trackId: trackId) - localPeer = localPeer.withoutTrack(trackId: trackId) + localEndpoint = localEndpoint.withoutTrack(trackId: trackId) engineCommunication.renegotiateTracks() return true } - /// Returns information about the current local peer - public func currentPeer() -> Peer { - return localPeer + /// Returns information about the current local endpoint + public func currentEndpoint() -> Endpoint { + return localEndpoint } /** @@ -326,17 +326,17 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } /** - Updates the metadata for the current peer. + Updates the metadata for the current endpoint. - Parameters: - - peerMetadata: Data about this peer that other peers will receive upon joining. + - metadata: Data about this endpoint that other endpoints will receive upon being added. If the metadata is different from what is already tracked in the room, the optional - callback `onPeerUpdated` will be triggered for other peers in the room. + callback `onEndpointUpdated` will be triggered for other peers in the room. */ - public func updatePeerMetadata(peerMetadata: Metadata) { - engineCommunication.updatePeerMetadata(peerMetadata: peerMetadata) - localPeer = localPeer.with(metadata: peerMetadata) + public func updateEndpointMetadata(metadata: Metadata) { + engineCommunication.updateEndpointMetadata(metadata: metadata) + localEndpoint = localEndpoint.with(metadata: metadata) } /** @@ -351,7 +351,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje */ public func updateTrackMetadata(trackId: String, trackMetadata: Metadata) { engineCommunication.updateTrackMetadata(trackId: trackId, trackMetadata: trackMetadata) - localPeer = localPeer.withTrack(trackId: trackId, metadata: trackMetadata) + localEndpoint = localEndpoint.withTrack(trackId: trackId, metadata: trackMetadata) } /** @@ -385,7 +385,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje peerConnectionManager.addTrack(track: track, localStreamId: screencastStreamId) - localPeer = localPeer.withTrack(trackId: track.rtcTrack().trackId, metadata: metadata) + localEndpoint = localEndpoint.withTrack(trackId: track.rtcTrack().trackId, metadata: metadata) engineCommunication.renegotiateTracks() } @@ -434,16 +434,16 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } } - func onPeerAccepted(peerId: String, peersInRoom: [Peer]) { - localPeer = localPeer.with(id: peerId) + func onConnected(endpointId: String, otherEndpoints: [Endpoint]) { + localEndpoint = localEndpoint.with(id: endpointId) // initialize all present peers - peersInRoom.forEach { peer in - self.remotePeers[peer.id] = peer + otherEndpoints.forEach { endpoint in + self.remoteEndpoints[endpoint.id] = endpoint // initialize peer's track contexts - peer.trackIdToMetadata?.forEach { trackId, metadata in - let context = TrackContext(track: nil, peer: peer, trackId: trackId, metadata: metadata) + endpoint.trackIdToMetadata?.forEach { trackId, metadata in + let context = TrackContext(track: nil, enpoint: endpoint, trackId: trackId, metadata: metadata) self.trackContexts[trackId] = context @@ -454,39 +454,39 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } notify { - $0.onJoinSuccess(peerID: peerId, peersInRoom: peersInRoom) + $0.onConnected(endpointId: endpointId, otherEndpoints: otherEndpoints) } engineCommunication.renegotiateTracks() } - func onPeerDenied() { + func onConnectionError() { notify { - $0.onJoinError(metadata: [:]) + $0.onConnectionError(metadata: [:] as [String: Any]) } } - func onPeerJoined(peer: Peer) { - guard peer.id != localPeer.id else { + func onEndpointAdded(endpoint: Endpoint) { + guard endpoint.id != localEndpoint.id else { return } - remotePeers[peer.id] = peer + remoteEndpoints[endpoint.id] = endpoint notify { - $0.onPeerJoined(peer: peer) + $0.onEndpointAdded(endpoint: endpoint) } } - func onPeerLeft(peerId: String) { - guard let peer = remotePeers[peerId] else { - sdkLogger.error("Failed to process PeerLeft event: Peer not found: \(peerId)") + func onEndpointRemoved(endpointId: String) { + guard let endpoint = remoteEndpoints[endpointId] else { + sdkLogger.error("Failed to process EndpointRemoved event: Endpoint not found: \(endpointId)") return } - remotePeers.removeValue(forKey: peer.id) + remoteEndpoints.removeValue(forKey: endpoint.id) // for a leaving peer clear his track contexts - if let trackIds = peer.trackIdToMetadata?.keys { + if let trackIds = endpoint.trackIdToMetadata?.keys { let contexts = trackIds.compactMap { id in self.trackContexts[id] } @@ -503,23 +503,23 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } notify { - $0.onPeerLeft(peer: peer) + $0.onEndpointRemoved(endpoint: endpoint) } } - func onPeerUpdated(peerId: String, peerMetadata: Metadata) { - guard var peer = remotePeers[peerId] else { - sdkLogger.error("Failed to process PeerUpdated event: Peer not found: \(peerId)") + func onEndpointUpdated(endpointId: String, metadata: Metadata) { + guard var endpoint = remoteEndpoints[endpointId] else { + sdkLogger.error("Failed to process EndpointUpdated event: Endpoint not found: \(endpointId)") return } // update peer's metadata - peer = peer.with(metadata: peerMetadata) + endpoint = endpoint.with(metadata: metadata) - remotePeers.updateValue(peer, forKey: peer.id) + remoteEndpoints.updateValue(endpoint, forKey: endpoint.id) notify { - $0.onPeerUpdated(peer: peer) + $0.onEndpointUpdated(endpoint: endpoint) } } @@ -534,7 +534,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje if let sdp = sdp, let midToTrackId = midToTrackId { self.engineCommunication.sdpOffer( - sdp: sdp, trackIdToTrackMetadata: self.localPeer.trackIdToMetadata ?? [:], + sdp: sdp, trackIdToTrackMetadata: self.localEndpoint.trackIdToMetadata ?? [:], midToTrackId: midToTrackId) } @@ -551,24 +551,24 @@ public class MembraneRTC: MulticastDelegate, ObservableObje peerConnectionManager.onRemoteCandidate(candidate: candidate) } - func onTracksAdded(peerId: String, trackIdToMetadata: [String: Metadata]) { + func onTracksAdded(endpointId: String, trackIdToMetadata: [String: Metadata]) { // ignore local participant - guard localPeer.id != peerId else { + guard localEndpoint.id != endpointId else { return } - guard var peer = remotePeers[peerId] else { - sdkLogger.error("Failed to process TracksAdded event: Peer not found: \(peerId)") + guard var endpoint = remoteEndpoints[endpointId] else { + sdkLogger.error("Failed to process TracksAdded event: Endpoint not found: \(endpointId)") return } // update tracks of the remote peer - peer = peer.with(trackIdToMetadata: trackIdToMetadata) - remotePeers[peer.id] = peer + endpoint = endpoint.with(trackIdToMetadata: trackIdToMetadata) + remoteEndpoints[endpoint.id] = endpoint // for each track create a corresponding track context - peer.trackIdToMetadata?.forEach { trackId, metadata in - let context = TrackContext(track: nil, peer: peer, trackId: trackId, metadata: metadata) + endpoint.trackIdToMetadata?.forEach { trackId, metadata in + let context = TrackContext(track: nil, enpoint: endpoint, trackId: trackId, metadata: metadata) self.trackContexts[trackId] = context @@ -578,9 +578,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } } - func onTracksRemoved(peerId: String, trackIds: [String]) { - guard let _ = remotePeers[peerId] else { - sdkLogger.error("Failed to process TracksRemoved event: Peer not found: \(peerId)") + func onTracksRemoved(endpointId: String, trackIds: [String]) { + guard let _ = remoteEndpoints[endpointId] else { + sdkLogger.error("Failed to process TracksRemoved event: Endpoint not found: \(endpointId)") return } @@ -599,7 +599,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } } - func onTrackUpdated(peerId: String, trackId: String, metadata: Metadata) { + func onTrackUpdated(endpointId: String, trackId: String, metadata: Metadata) { guard let context = self.trackContexts[trackId] else { sdkLogger.error("Failed to process TrackUpdated event: Track not found: \(trackId)") return @@ -612,12 +612,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } } - func onTrackEncodingChanged(peerId: String, trackId: String, encoding: String, encodingReason: String) { - self.notify { - $0.onTrackEncodingChanged( - peerId: peerId, trackId: trackId, - encoding: encoding) - } + func onTrackEncodingChanged(endpointId: String, trackId: String, encoding: String, encodingReason: String) { if let trackEncoding = TrackEncoding.fromString(encoding), let trackContext = self.trackContexts[trackId], let encodingReasonEnum = EncodingReason(rawValue: encodingReason) @@ -641,17 +636,6 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } } - func onRemoved(peerId: String, reason: String) { - guard peerId == localPeer.id else { - sdkLogger.error("Received onRemoved media event, but it does not refer to the local peer") - return - } - - notify { - $0.onRemoved(reason: reason) - } - } - /// Sends the local ice candidate to the `Membrane RTC Engine` instance via transport layer. func onLocalIceCandidate(candidate: RTCIceCandidate) { engineCommunication.localCandidate(sdp: candidate.sdp, sdpMLineIndex: candidate.sdpMLineIndex) diff --git a/Sources/MembraneRTC/MembraneRTCDelegate.swift b/Sources/MembraneRTC/MembraneRTCDelegate.swift index a1cb25f1..bd5d05cb 100644 --- a/Sources/MembraneRTC/MembraneRTCDelegate.swift +++ b/Sources/MembraneRTC/MembraneRTCDelegate.swift @@ -4,10 +4,10 @@ public protocol MembraneRTCDelegate { func onSendMediaEvent(event: SerializedMediaEvent) /// Callback invoked when the client has been approved to participate in session. - func onJoinSuccess(peerID: String, peersInRoom: [Peer]) + func onConnected(endpointId: String, otherEndpoints: [Endpoint]) /// Callback invoked when client has been denied access to enter the room. - func onJoinError(metadata: Any) + func onConnectionError(metadata: Any) /// Callback invoked a track is ready to be played. func onTrackReady(ctx: TrackContext) @@ -21,23 +21,16 @@ public protocol MembraneRTCDelegate { /// Callback invoked when track's metadata gets updated. func onTrackUpdated(ctx: TrackContext) - /// Callback invoked when a new peer joins the room. - func onPeerJoined(peer: Peer) + /// Callback invoked when a new endpoint is added.. + func onEndpointAdded(endpoint: Endpoint) - /// Callback invoked when a peer leaves the room. + /// Callback invoked when an endpoint is removed from the room. /// - /// When a peer with active track leaves the room, `onTrackRemoved` will be called for all their tracks beforehand. - func onPeerLeft(peer: Peer) + /// When an endpoint with active track leaves the room, `onTrackRemoved` will be called for all endpoint's tracks beforehand. + func onEndpointRemoved(endpoint: Endpoint) - /// Callback invoked when peer's metadata gets updated. - func onPeerUpdated(peer: Peer) - - /// Callback invoked every time a local peer is removed by the server - func onRemoved(reason: String) - - /// Callback invoked when received track encoding has changed - @available(*, deprecated, message: "Deprecated, use TrackContext::setOnEncodingChangedListener") - func onTrackEncodingChanged(peerId: String, trackId: String, encoding: String) + /// Callback invoked when endpoint's metadata gets updated. + func onEndpointUpdated(endpoint: Endpoint) ///Called every time the server estimates client's bandwidth. ///estimation - client's available incoming bitrate estimated @@ -46,14 +39,6 @@ public protocol MembraneRTCDelegate { } extension MembraneRTCDelegate { - public func onTrackEncodingChanged(peerId: String, trackId: String, encoding: String) { - sdkLogger.info("Track encoding changed \(trackId) -> \(encoding)") - } - - public func onRemoved(reason: String) { - sdkLogger.error("Peer removed, reason: \(reason)") - } - public func onBandwidthEstimationChanged(estimation: Int) { sdkLogger.info("Bandwidth estimation changed \(estimation)") } diff --git a/Sources/MembraneRTC/PeerConnectionManager.swift b/Sources/MembraneRTC/PeerConnectionManager.swift index e8201d3e..64f64a5b 100644 --- a/Sources/MembraneRTC/PeerConnectionManager.swift +++ b/Sources/MembraneRTC/PeerConnectionManager.swift @@ -433,7 +433,7 @@ internal class PeerConnectionManager: NSObject, RTCPeerConnectionDelegate { if line.hasPrefix(prefix) { let lineSuffix = String(line.suffix(from: prefix.endIndex)) - var encodings = lineSuffix.components(separatedBy: ";") + let encodings = lineSuffix.components(separatedBy: ";") var newEncodings = [String]() for encoding in encodings { diff --git a/Sources/MembraneRTC/RTCEngineCommunication.swift b/Sources/MembraneRTC/RTCEngineCommunication.swift index 18935c56..26c9f7c0 100644 --- a/Sources/MembraneRTC/RTCEngineCommunication.swift +++ b/Sources/MembraneRTC/RTCEngineCommunication.swift @@ -8,12 +8,12 @@ internal class RTCEngineCommunication { self.engineListener = engineListener } - func join(peerMetadata: Metadata) { - sendEvent(event: JoinEvent(metadata: peerMetadata)) + func connect(metadata: Metadata) { + sendEvent(event: ConnectEvent(metadata: metadata)) } - func updatePeerMetadata(peerMetadata: Metadata) { - sendEvent(event: UpdatePeerMetadata(metadata: peerMetadata)) + func updateEndpointMetadata(metadata: Metadata) { + sendEvent(event: UpdateEndpointMetadata(metadata: metadata)) } func updateTrackMetadata(trackId: String, trackMetadata: Metadata) { @@ -52,21 +52,22 @@ internal class RTCEngineCommunication { return } switch event.type { - case .PeerAccepted: - let peerAccepted = event as! PeerAcceptedEvent - engineListener.onPeerAccepted(peerId: peerAccepted.data.id, peersInRoom: peerAccepted.data.peersInRoom) - case .PeerJoined: - let peerJoined = event as! PeerJoinedEvent - engineListener.onPeerJoined(peer: peerJoined.data.peer) - case .PeerLeft: - let peerLeft = event as! PeerLeftEvent - engineListener.onPeerLeft(peerId: peerLeft.data.peerId) - case .PeerUpdated: - let peerUpdated = event as! PeerUpdateEvent - engineListener.onPeerUpdated(peerId: peerUpdated.data.peerId, peerMetadata: peerUpdated.data.metadata) - case .PeerRemoved: - let peerRemoved = event as! PeerRemovedEvent - engineListener.onRemoved(peerId: peerRemoved.data.peerId, reason: peerRemoved.data.reason) + case .Connected: + let connected = event as! ConnectedEvent + engineListener.onConnected(endpointId: connected.data.id, otherEndpoints: connected.data.otherEndpoints) + case .EndpointAdded: + let endpointAdded = event as! EndpointAddedEvent + engineListener.onEndpointAdded( + endpoint: Endpoint( + id: endpointAdded.data.id, type: endpointAdded.data.type, metadata: endpointAdded.data.metadata, + trackIdToMetadata: endpointAdded.data.trackIdToMetadata)) + case .EndpointRemoved: + let endpointRemoved = event as! EndpointRemovedEvent + engineListener.onEndpointRemoved(endpointId: endpointRemoved.data.id) + case .EndpointUpdated: + let endpointUpdated = event as! EndpointUpdatedEvent + engineListener.onEndpointUpdated( + endpointId: endpointUpdated.data.endpointId, metadata: endpointUpdated.data.metadata) case .OfferData: let offerData = event as! OfferDataEvent engineListener.onOfferData( @@ -79,14 +80,15 @@ internal class RTCEngineCommunication { case .TracksAdded: let tracksAdded = event as! TracksAddedEvent engineListener.onTracksAdded( - peerId: tracksAdded.data.peerId, trackIdToMetadata: tracksAdded.data.trackIdToMetadata) + endpointId: tracksAdded.data.endpointId, trackIdToMetadata: tracksAdded.data.trackIdToMetadata) case .TracksRemoved: let tracksRemoved = event as! TracksRemovedEvent - engineListener.onTracksRemoved(peerId: tracksRemoved.data.peerId, trackIds: tracksRemoved.data.trackIds) + engineListener.onTracksRemoved( + endpointId: tracksRemoved.data.endpointId, trackIds: tracksRemoved.data.trackIds) case .TrackUpdated: let tracksUpdated = event as! TracksUpdatedEvent engineListener.onTrackUpdated( - peerId: tracksUpdated.data.peerId, trackId: tracksUpdated.data.trackId, + endpointId: tracksUpdated.data.endpointId, trackId: tracksUpdated.data.trackId, metadata: tracksUpdated.data.metadata) case .SdpAnswer: let sdpAnswer = event as! SdpAnswerEvent @@ -95,7 +97,7 @@ internal class RTCEngineCommunication { case .EncodingSwitched: let encodingSwitched = event as! EncodingSwitchedEvent engineListener.onTrackEncodingChanged( - peerId: encodingSwitched.data.peerId, trackId: encodingSwitched.data.trackId, + endpointId: encodingSwitched.data.endpointId, trackId: encodingSwitched.data.trackId, encoding: encodingSwitched.data.encoding, encodingReason: encodingSwitched.data.reason) case .VadNotification: let vadNotification = event as! VadNotificationEvent diff --git a/Sources/MembraneRTC/RTCEngineListener.swift b/Sources/MembraneRTC/RTCEngineListener.swift index 8a4472be..1f54a17f 100644 --- a/Sources/MembraneRTC/RTCEngineListener.swift +++ b/Sources/MembraneRTC/RTCEngineListener.swift @@ -1,18 +1,17 @@ internal protocol RTCEngineListener { func onSendMediaEvent(event: SerializedMediaEvent) - func onPeerAccepted(peerId: String, peersInRoom: [Peer]) - func onPeerDenied() - func onPeerJoined(peer: Peer) - func onPeerLeft(peerId: String) - func onPeerUpdated(peerId: String, peerMetadata: Metadata) + func onConnected(endpointId: String, otherEndpoints: [Endpoint]) + func onConnectionError() + func onEndpointAdded(endpoint: Endpoint) + func onEndpointRemoved(endpointId: String) + func onEndpointUpdated(endpointId: String, metadata: Metadata) func onOfferData(integratedTurnServers: [OfferDataEvent.TurnServer], tracksTypes: [String: Int]) func onSdpAnswer(type: String, sdp: String, midToTrackId: [String: String?]) func onRemoteCandidate(candidate: String, sdpMLineIndex: Int32, sdpMid: String?) - func onTracksAdded(peerId: String, trackIdToMetadata: [String: Metadata]) - func onTracksRemoved(peerId: String, trackIds: [String]) - func onTrackUpdated(peerId: String, trackId: String, metadata: Metadata) - func onTrackEncodingChanged(peerId: String, trackId: String, encoding: String, encodingReason: String) + func onTracksAdded(endpointId: String, trackIdToMetadata: [String: Metadata]) + func onTracksRemoved(endpointId: String, trackIds: [String]) + func onTrackUpdated(endpointId: String, trackId: String, metadata: Metadata) + func onTrackEncodingChanged(endpointId: String, trackId: String, encoding: String, encodingReason: String) func onVadNotification(trackId: String, status: String) func onBandwidthEstimation(estimation: Int) - func onRemoved(peerId: String, reason: String) } diff --git a/Sources/MembraneRTC/Types/Peer.swift b/Sources/MembraneRTC/Types/Endpoint.swift similarity index 63% rename from Sources/MembraneRTC/Types/Peer.swift rename to Sources/MembraneRTC/Types/Endpoint.swift index 1d3cf966..73cd999d 100644 --- a/Sources/MembraneRTC/Types/Peer.swift +++ b/Sources/MembraneRTC/Types/Endpoint.swift @@ -1,19 +1,22 @@ -public struct Peer: Codable { +public struct Endpoint: Codable { public let id: String + public let type: String public let metadata: Metadata public let trackIdToMetadata: [String: Metadata]? - public init(id: String, metadata: Metadata, trackIdToMetadata: [String: Metadata]?) { + public init(id: String, type: String, metadata: Metadata, trackIdToMetadata: [String: Metadata]?) { self.id = id + self.type = type self.metadata = metadata self.trackIdToMetadata = trackIdToMetadata } public func with( - id: String? = nil, metadata: Metadata? = nil, trackIdToMetadata: [String: Metadata]? = nil + id: String? = nil, type: String? = nil, metadata: Metadata? = nil, trackIdToMetadata: [String: Metadata]? = nil ) -> Self { - return Peer( + return Endpoint( id: id ?? self.id, + type: type ?? self.type, metadata: metadata ?? self.metadata, trackIdToMetadata: trackIdToMetadata ?? self.trackIdToMetadata ) @@ -23,23 +26,24 @@ public struct Peer: Codable { var newTrackIdToMetadata = self.trackIdToMetadata newTrackIdToMetadata?[trackId] = metadata - return Peer(id: self.id, metadata: self.metadata, trackIdToMetadata: newTrackIdToMetadata) + return Endpoint(id: self.id, type: self.type, metadata: self.metadata, trackIdToMetadata: newTrackIdToMetadata) } public func withoutTrack(trackId: String) -> Self { var newTrackIdToMetadata = self.trackIdToMetadata newTrackIdToMetadata?.removeValue(forKey: trackId) - return Peer(id: self.id, metadata: self.metadata, trackIdToMetadata: newTrackIdToMetadata) + return Endpoint(id: self.id, type: self.type, metadata: self.metadata, trackIdToMetadata: newTrackIdToMetadata) } enum CodingKeys: String, CodingKey { - case id, metadata, trackIdToMetadata + case id, type, metadata, trackIdToMetadata } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decode(String.self, forKey: .id) + self.type = try container.decode(String.self, forKey: .type) self.metadata = try container.decode(Metadata.self, forKey: .metadata) self.trackIdToMetadata = try container.decodeIfPresent( [String: Metadata].self, forKey: .trackIdToMetadata) diff --git a/Sources/MembraneRTC/Types/TrackContext.swift b/Sources/MembraneRTC/Types/TrackContext.swift index 479209e1..ef972ac5 100644 --- a/Sources/MembraneRTC/Types/TrackContext.swift +++ b/Sources/MembraneRTC/Types/TrackContext.swift @@ -3,7 +3,7 @@ public class TrackContext { public internal(set) var track: RemoteTrack? ///Peer this track comes from. - public let peer: Peer + public let endpoint: Endpoint /// Track id. It is generated by RTC engine and takes form `peer_id:`. public let trackId: String @@ -33,9 +33,9 @@ public class TrackContext { } } - init(track: RemoteTrack? = nil, peer: Peer, trackId: String, metadata: Metadata) { + init(track: RemoteTrack? = nil, enpoint: Endpoint, trackId: String, metadata: Metadata) { self.track = track - self.peer = peer + self.endpoint = enpoint self.trackId = trackId self.metadata = metadata } From f46f2859641b9cac70cf37fff29f6b5c0c771085 Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Tue, 13 Jun 2023 16:56:58 +0200 Subject: [PATCH 4/8] Fix error related to missing arclib libraries (#39) --- MembraneRTC.podspec | 3 +-- .../xcshareddata/swiftpm/Package.resolved | 9 --------- Package.swift | 2 -- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/MembraneRTC.podspec b/MembraneRTC.podspec index 9c4e6582..c5990ba3 100644 --- a/MembraneRTC.podspec +++ b/MembraneRTC.podspec @@ -25,8 +25,7 @@ Pod::Spec.new do |s| s.dependency 'SwiftProtobuf' s.dependency 'PromisesSwift' s.dependency 'SwiftPhoenixClient', '~> 4.0.0' - s.dependency 'Logging' - s.dependency 'SwiftCollection' + s.dependency 'SwiftLogJellyfish', '1.5.2' s.pod_target_xcconfig = { 'ENABLE_BITCODE' => 'NO' } s.subspec "Broadcast" do |spec| diff --git a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved index ef110cdc..5ab9838b 100644 --- a/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MembraneVideoroomDemo.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -37,15 +37,6 @@ "version": "3.1.2" } }, - { - "package": "swift-collections", - "repositoryURL": "https://github.com/apple/swift-collections.git", - "state": { - "branch": null, - "revision": "937e904258d22af6e447a0b72c0bc67583ef64a2", - "version": "1.0.4" - } - }, { "package": "SwiftDocCPlugin", "repositoryURL": "https://github.com/apple/swift-docc-plugin", diff --git a/Package.swift b/Package.swift index 34ffdca8..125bded3 100644 --- a/Package.swift +++ b/Package.swift @@ -27,7 +27,6 @@ let package = Package( name: "SwiftPhoenixClient", url: "https://github.com/davidstump/SwiftPhoenixClient.git", .upToNextMajor(from: "4.0.0")), .package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.4.2")), - .package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.1")), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), ], targets: [ @@ -39,7 +38,6 @@ let package = Package( "WebRTC", "SwiftProtobuf", "Promises", "SwiftPhoenixClient", .product(name: "FBLPromises", package: "Promises"), .product(name: "Logging", package: "swift-log"), - .product(name: "Collections", package: "swift-collections"), ], path: "Sources" ) From 03f6dc340239c138e59ce016e37782a70b51eea3 Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Wed, 14 Jun 2023 16:39:42 +0200 Subject: [PATCH 5/8] Fix threading issues (#40) --- .../Capturers/ScreenBroadcastCapturer.swift | 4 +- Sources/MembraneRTC/MembraneRTC.swift | 205 ++++++++++-------- .../PeerConnectionFactoryWrapper.swift | 20 +- 3 files changed, 126 insertions(+), 103 deletions(-) diff --git a/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift b/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift index c92ef7e8..81f2d0d5 100644 --- a/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift +++ b/Sources/MembraneRTC/Media/Capturers/ScreenBroadcastCapturer.swift @@ -84,9 +84,7 @@ class ScreenBroadcastCapturer: RTCVideoCapturer, VideoCapturer { private var timeoutTimer: Timer? - internal let supportedPixelFormats = DispatchQueue.webRTC.sync { - RTCCVPixelBuffer.supportedPixelFormats() - } + internal let supportedPixelFormats = RTCCVPixelBuffer.supportedPixelFormats() /** Creates a broadcast screen capturer. diff --git a/Sources/MembraneRTC/MembraneRTC.swift b/Sources/MembraneRTC/MembraneRTC.swift index e5aa7211..e46ece03 100644 --- a/Sources/MembraneRTC/MembraneRTC.swift +++ b/Sources/MembraneRTC/MembraneRTC.swift @@ -104,11 +104,13 @@ public class MembraneRTC: MulticastDelegate, ObservableObje public static func create(with options: CreateOptions = CreateOptions(), delegate: MembraneRTCDelegate) -> MembraneRTC { - let client = MembraneRTC(config: RTCConfiguration(), encoder: options.encoder) + DispatchQueue.webRTC.sync { + let client = MembraneRTC(config: RTCConfiguration(), encoder: options.encoder) - client.add(delegate: delegate) + client.add(delegate: delegate) - return client + return client + } } // Default ICE server when no turn servers are specified @@ -122,24 +124,28 @@ public class MembraneRTC: MulticastDelegate, ObservableObje /// /// Once completed either `onConnected` or `onConnectError` of client's delegate gets invovked. public func connect(metadata: Metadata) { - guard state == .awaitingConnect else { - return - } + DispatchQueue.webRTC.sync { + guard state == .awaitingConnect else { + return + } - localEndpoint = localEndpoint.with(metadata: metadata) + localEndpoint = localEndpoint.with(metadata: metadata) - engineCommunication.connect(metadata: metadata) + engineCommunication.connect(metadata: metadata) + } } /// Disconnects from the `Membrane RTC Engine` transport and closes the exisitng `RTCPeerConnection` /// /// Once the `disconnect` gets invoked the client can't be reused and user should create a new client instance instead. public func disconnect() { - localTracks.forEach { track in - track.stop() - } + DispatchQueue.webRTC.sync { + localTracks.forEach { track in + track.stop() + } - peerConnectionManager.close() + peerConnectionManager.close() + } } /** @@ -150,7 +156,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje * @param mediaEvent - String data received over custom signalling layer. */ public func receiveMediaEvent(mediaEvent: SerializedMediaEvent) { - engineCommunication.onEvent(serializedEvent: mediaEvent) + DispatchQueue.webRTC.sync { + engineCommunication.onEvent(serializedEvent: mediaEvent) + } } /** @@ -168,28 +176,31 @@ public class MembraneRTC: MulticastDelegate, ObservableObje public func createVideoTrack(videoParameters: VideoParameters, metadata: Metadata, captureDeviceId: String? = nil) -> LocalVideoTrack { - let videoTrack = LocalVideoTrack.create( - for: .camera, videoParameters: videoParameters, peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) + DispatchQueue.webRTC.sync { + let videoTrack = LocalVideoTrack.create( + for: .camera, videoParameters: videoParameters, + peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) - if state == .connected { - peerConnectionManager.addTrack(track: videoTrack, localStreamId: localStreamId) - } + if state == .connected { + peerConnectionManager.addTrack(track: videoTrack, localStreamId: localStreamId) + } - if let captureDeviceId = captureDeviceId, let videoTrack = videoTrack as? LocalCameraVideoTrack { - videoTrack.switchCamera(deviceId: captureDeviceId) - } + if let captureDeviceId = captureDeviceId, let videoTrack = videoTrack as? LocalCameraVideoTrack { + videoTrack.switchCamera(deviceId: captureDeviceId) + } - videoTrack.start() + videoTrack.start() - localTracks.append(videoTrack) + localTracks.append(videoTrack) - localEndpoint = localEndpoint.withTrack(trackId: videoTrack.rtcTrack().trackId, metadata: metadata) + localEndpoint = localEndpoint.withTrack(trackId: videoTrack.rtcTrack().trackId, metadata: metadata) - if state == .connected { - engineCommunication.renegotiateTracks() - } + if state == .connected { + engineCommunication.renegotiateTracks() + } - return videoTrack + return videoTrack + } } /** @@ -203,23 +214,25 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - Returns: `LocalAudioTrack` instance that user then can use for things such as front / back camera switch. */ public func createAudioTrack(metadata: Metadata) -> LocalAudioTrack { - let audioTrack = LocalAudioTrack(peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) + DispatchQueue.webRTC.sync { + let audioTrack = LocalAudioTrack(peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) - if state == .connected { - peerConnectionManager.addTrack(track: audioTrack, localStreamId: localStreamId) - } + if state == .connected { + peerConnectionManager.addTrack(track: audioTrack, localStreamId: localStreamId) + } - audioTrack.start() + audioTrack.start() - localTracks.append(audioTrack) + localTracks.append(audioTrack) - localEndpoint = localEndpoint.withTrack(trackId: audioTrack.rtcTrack().trackId, metadata: metadata) + localEndpoint = localEndpoint.withTrack(trackId: audioTrack.rtcTrack().trackId, metadata: metadata) - if state == .connected { - engineCommunication.renegotiateTracks() - } + if state == .connected { + engineCommunication.renegotiateTracks() + } - return audioTrack + return audioTrack + } } /** @@ -242,34 +255,36 @@ public class MembraneRTC: MulticastDelegate, ObservableObje appGroup: String, videoParameters: VideoParameters, metadata: Metadata, onStart: @escaping (_ track: LocalScreenBroadcastTrack) -> Void, onStop: @escaping () -> Void ) -> LocalScreenBroadcastTrack { - let screensharingTrack = LocalScreenBroadcastTrack( - appGroup: appGroup, videoParameters: videoParameters, - peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) - localTracks.append(screensharingTrack) - - broadcastScreenshareReceiver = ScreenBroadcastNotificationReceiver( - onStart: { [weak self, weak screensharingTrack] in - guard let track = screensharingTrack else { - return - } + DispatchQueue.webRTC.sync { + let screensharingTrack = LocalScreenBroadcastTrack( + appGroup: appGroup, videoParameters: videoParameters, + peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) + localTracks.append(screensharingTrack) + + broadcastScreenshareReceiver = ScreenBroadcastNotificationReceiver( + onStart: { [weak self, weak screensharingTrack] in + guard let track = screensharingTrack else { + return + } - DispatchQueue.main.async { - self?.setupScreencastTrack(track: track, metadata: metadata) - onStart(track) - } - }, - onStop: { [weak self, weak screensharingTrack] in - DispatchQueue.main.async { - if let track = screensharingTrack { - self?.removeTrack(trackId: track.rtcTrack().trackId) + DispatchQueue.main.async { + self?.setupScreencastTrack(track: track, metadata: metadata) + onStart(track) } - onStop() - } - }) + }, + onStop: { [weak self, weak screensharingTrack] in + DispatchQueue.main.async { + if let track = screensharingTrack { + self?.removeTrack(trackId: track.rtcTrack().trackId) + } + onStop() + } + }) - screensharingTrack.delegate = broadcastScreenshareReceiver - screensharingTrack.start() - return screensharingTrack + screensharingTrack.delegate = broadcastScreenshareReceiver + screensharingTrack.start() + return screensharingTrack + } } /** @@ -282,25 +297,29 @@ public class MembraneRTC: MulticastDelegate, ObservableObje */ @discardableResult public func removeTrack(trackId: String) -> Bool { - guard let index = localTracks.firstIndex(where: { $0.rtcTrack().trackId == trackId }) else { - return false - } + DispatchQueue.webRTC.sync { + guard let index = localTracks.firstIndex(where: { $0.rtcTrack().trackId == trackId }) else { + return false + } - let track = localTracks.remove(at: index) - track.stop() + let track = localTracks.remove(at: index) + track.stop() - peerConnectionManager.removeTrack(trackId: trackId) + peerConnectionManager.removeTrack(trackId: trackId) - localEndpoint = localEndpoint.withoutTrack(trackId: trackId) + localEndpoint = localEndpoint.withoutTrack(trackId: trackId) - engineCommunication.renegotiateTracks() + engineCommunication.renegotiateTracks() - return true + return true + } } /// Returns information about the current local endpoint public func currentEndpoint() -> Endpoint { - return localEndpoint + DispatchQueue.webRTC.sync { + return localEndpoint + } } /** @@ -311,7 +330,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - encoding: an encoding that will be enabled */ public func enableTrackEncoding(trackId: String, encoding: TrackEncoding) { - setTrackEncoding(trackId: trackId, encoding: encoding, enabled: true) + DispatchQueue.webRTC.sync { + setTrackEncoding(trackId: trackId, encoding: encoding, enabled: true) + } } /** @@ -322,7 +343,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - encoding: an encoding that will be disabled */ public func disableTrackEncoding(trackId: String, encoding: TrackEncoding) { - setTrackEncoding(trackId: trackId, encoding: encoding, enabled: false) + DispatchQueue.webRTC.sync { + setTrackEncoding(trackId: trackId, encoding: encoding, enabled: false) + } } /** @@ -335,8 +358,10 @@ public class MembraneRTC: MulticastDelegate, ObservableObje callback `onEndpointUpdated` will be triggered for other peers in the room. */ public func updateEndpointMetadata(metadata: Metadata) { - engineCommunication.updateEndpointMetadata(metadata: metadata) - localEndpoint = localEndpoint.with(metadata: metadata) + DispatchQueue.webRTC.sync { + engineCommunication.updateEndpointMetadata(metadata: metadata) + localEndpoint = localEndpoint.with(metadata: metadata) + } } /** @@ -350,8 +375,10 @@ public class MembraneRTC: MulticastDelegate, ObservableObje callback `onTrackUpdated` will be triggered for other peers in the room. */ public func updateTrackMetadata(trackId: String, trackMetadata: Metadata) { - engineCommunication.updateTrackMetadata(trackId: trackId, trackMetadata: trackMetadata) - localEndpoint = localEndpoint.withTrack(trackId: trackId, metadata: trackMetadata) + DispatchQueue.webRTC.sync { + engineCommunication.updateTrackMetadata(trackId: trackId, trackMetadata: trackMetadata) + localEndpoint = localEndpoint.withTrack(trackId: trackId, metadata: trackMetadata) + } } /** @@ -364,7 +391,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - bandwidth: bandwidth in kbps */ public func setTrackBandwidth(trackId: String, bandwidth: BandwidthLimit) { - peerConnectionManager.setTrackBandwidth(trackId: trackId, bandwidth: bandwidth) + DispatchQueue.webRTC.sync { + peerConnectionManager.setTrackBandwidth(trackId: trackId, bandwidth: bandwidth) + } } /** @@ -376,7 +405,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - bandwidth: bandwidth in kbps */ public func setEncodingBandwidth(trackId: String, encoding: String, bandwidth: BandwidthLimit) { - peerConnectionManager.setEncodingBandwidth(trackId: trackId, encoding: encoding, bandwidth: bandwidth) + DispatchQueue.webRTC.sync { + peerConnectionManager.setEncodingBandwidth(trackId: trackId, encoding: encoding, bandwidth: bandwidth) + } } /// Adds given broadcast track to the peer connection and forces track renegotiation. @@ -402,7 +433,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - encoding: an encoding to receive */ public func setTargetTrackEncoding(trackId: String, encoding: TrackEncoding) { - engineCommunication.setTargetTrackEncoding(trackId: trackId, encoding: encoding) + DispatchQueue.webRTC.sync { + engineCommunication.setTargetTrackEncoding(trackId: trackId, encoding: encoding) + } } private func setTrackEncoding(trackId: String, encoding: TrackEncoding, enabled: Bool) { @@ -415,7 +448,9 @@ public class MembraneRTC: MulticastDelegate, ObservableObje - Returns: a map containing statistics */ public func getStats() -> [String: RTCStats] { - return peerConnectionManager.getStats() + DispatchQueue.webRTC.sync { + return peerConnectionManager.getStats() + } } /** @@ -627,7 +662,6 @@ public class MembraneRTC: MulticastDelegate, ObservableObje { trackContext.vadStatus = vadStatus } - } func onBandwidthEstimation(estimation: Int) { @@ -678,5 +712,4 @@ public class MembraneRTC: MulticastDelegate, ObservableObje extension DispatchQueue { static let webRTC = DispatchQueue(label: "membrane.rtc.webRTC") - static let sdk = DispatchQueue(label: "membrane.rtc.sdk") } diff --git a/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift b/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift index 6b138318..0a2d0538 100644 --- a/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift +++ b/Sources/MembraneRTC/PeerConnectionFactoryWrapper.swift @@ -21,35 +21,27 @@ internal class PeerConnectionFactoryWrapper { func createPeerConnection(_ configuration: RTCConfiguration, constraints: RTCMediaConstraints) -> RTCPeerConnection? { - DispatchQueue.webRTC.sync { - factory.peerConnection(with: configuration, constraints: constraints, delegate: nil) - } + factory.peerConnection(with: configuration, constraints: constraints, delegate: nil) } func createAudioSource(_ constraints: RTCMediaConstraints?) -> RTCAudioSource { - DispatchQueue.webRTC.sync { - factory.audioSource(with: constraints) - } + factory.audioSource(with: constraints) } func createAudioTrack(source: RTCAudioSource) -> RTCAudioTrack { - DispatchQueue.webRTC.sync { - factory.audioTrack(with: source, trackId: UUID().uuidString) - } + factory.audioTrack(with: source, trackId: UUID().uuidString) } func createVideoCapturer() -> RTCVideoCapturer { - DispatchQueue.webRTC.sync { RTCVideoCapturer() } + RTCVideoCapturer() } func createVideoSource(forScreencast _: Bool = false) -> RTCVideoSource { - DispatchQueue.webRTC.sync { factory.videoSource() } + factory.videoSource() } func createVideoTrack(source: RTCVideoSource) -> RTCVideoTrack { - DispatchQueue.webRTC.sync { - factory.videoTrack(with: source, trackId: UUID().uuidString) - } + factory.videoTrack(with: source, trackId: UUID().uuidString) } } From d68ef73ed0a62dfda843dc2bd105a7853c26234d Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Thu, 15 Jun 2023 11:57:28 +0200 Subject: [PATCH 6/8] [RTC-279] Allow to create tracks immediately after onConnect callback (#41) * Allow to create tracks immediately after onConnect callback * Remove misleading comment --- .../Controllers/RoomController.swift | 46 ++++++++++--------- Sources/MembraneRTC/MembraneRTC.swift | 11 ++--- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/MembraneVideoroomDemo/Controllers/RoomController.swift b/MembraneVideoroomDemo/Controllers/RoomController.swift index 3606c5f3..d48da5a2 100644 --- a/MembraneVideoroomDemo/Controllers/RoomController.swift +++ b/MembraneVideoroomDemo/Controllers/RoomController.swift @@ -51,6 +51,7 @@ class RoomController: ObservableObject { var localParticipantId: String? var localScreensharingVideoId: String? var isFrontCamera: Bool = true + let displayName: String @Published var videoSimulcastConfig: SimulcastConfig = SimulcastConfig( enabled: true, activeEncodings: [TrackEncoding.l, TrackEncoding.m]) @@ -59,6 +60,7 @@ class RoomController: ObservableObject { init(_ room: MembraneRTC, _ displayName: String) { self.room = room + self.displayName = displayName participants = [:] participantVideos = [] @@ -66,26 +68,6 @@ class RoomController: ObservableObject { isCameraEnabled = true isScreensharingEnabled = false - let videoTrackMetadata = - [ - "user_id": displayName, "active": true, "type": "camera", - ] as [String: Any] - let audioTrackMetadata = - [ - "user_id": displayName, "active": true, "type": "audio", - ] as [String: Any] - - let preset = VideoParameters.presetHD43 - let videoParameters = VideoParameters( - dimensions: preset.dimensions.flip(), - maxBandwidth: TrackBandwidthLimit.SimulcastBandwidthLimit(["l": 150, "m": 500, "h": 1500]), - simulcastConfig: videoSimulcastConfig - ) - - localVideoTrack = room.createVideoTrack( - videoParameters: videoParameters, metadata: .init(videoTrackMetadata)) - localAudioTrack = room.createAudioTrack(metadata: .init(audioTrackMetadata)) - room.add(delegate: self) self.room?.connect(metadata: .init(["displayName": displayName])) @@ -325,8 +307,6 @@ extension RoomController: MembraneRTCDelegate { func onSendMediaEvent(event: SerializedMediaEvent) {} func onConnected(endpointId: String, otherEndpoints: [Endpoint]) { - localParticipantId = endpointId - let localParticipant = Participant(id: endpointId, displayName: "Me", isAudioTrackActive: true) let participants = otherEndpoints.map { endpoint in @@ -335,6 +315,28 @@ extension RoomController: MembraneRTCDelegate { isAudioTrackActive: false) } + let videoTrackMetadata = + [ + "user_id": displayName, "active": true, "type": "camera", + ] as [String: Any] + let audioTrackMetadata = + [ + "user_id": displayName, "active": true, "type": "audio", + ] as [String: Any] + + let preset = VideoParameters.presetHD43 + let videoParameters = VideoParameters( + dimensions: preset.dimensions.flip(), + maxBandwidth: TrackBandwidthLimit.SimulcastBandwidthLimit(["l": 150, "m": 500, "h": 1500]), + simulcastConfig: videoSimulcastConfig + ) + + localVideoTrack = room?.createVideoTrack( + videoParameters: videoParameters, metadata: .init(videoTrackMetadata)) + localAudioTrack = room?.createAudioTrack(metadata: .init(audioTrackMetadata)) + + localParticipantId = endpointId + DispatchQueue.main.async { self.participantVideos = participants.map { p in ParticipantVideo(id: p.id, participant: p, videoTrack: nil, isActive: false) diff --git a/Sources/MembraneRTC/MembraneRTC.swift b/Sources/MembraneRTC/MembraneRTC.swift index e46ece03..73962957 100644 --- a/Sources/MembraneRTC/MembraneRTC.swift +++ b/Sources/MembraneRTC/MembraneRTC.swift @@ -91,7 +91,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje } /** - Initializes MembraneRTC client and sets up local audio and video track. + Initializes MembraneRTC client. Should not be confused with joining the actual room, which is a separate process. @@ -195,9 +195,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje localEndpoint = localEndpoint.withTrack(trackId: videoTrack.rtcTrack().trackId, metadata: metadata) - if state == .connected { - engineCommunication.renegotiateTracks() - } + engineCommunication.renegotiateTracks() return videoTrack } @@ -227,9 +225,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje localEndpoint = localEndpoint.withTrack(trackId: audioTrack.rtcTrack().trackId, metadata: metadata) - if state == .connected { - engineCommunication.renegotiateTracks() - } + engineCommunication.renegotiateTracks() return audioTrack } @@ -491,7 +487,6 @@ public class MembraneRTC: MulticastDelegate, ObservableObje notify { $0.onConnected(endpointId: endpointId, otherEndpoints: otherEndpoints) } - engineCommunication.renegotiateTracks() } func onConnectionError() { From 71aab885fef4ac3bf3843c88e64c6895ed7c6578 Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Wed, 21 Jun 2023 15:03:23 +0200 Subject: [PATCH 7/8] Fix race condition (#42) --- Sources/MembraneRTC/MembraneRTC.swift | 8 ++------ Sources/MembraneRTC/PeerConnectionManager.swift | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Sources/MembraneRTC/MembraneRTC.swift b/Sources/MembraneRTC/MembraneRTC.swift index 73962957..563e54cc 100644 --- a/Sources/MembraneRTC/MembraneRTC.swift +++ b/Sources/MembraneRTC/MembraneRTC.swift @@ -181,9 +181,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje for: .camera, videoParameters: videoParameters, peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) - if state == .connected { - peerConnectionManager.addTrack(track: videoTrack, localStreamId: localStreamId) - } + peerConnectionManager.addTrack(track: videoTrack, localStreamId: localStreamId) if let captureDeviceId = captureDeviceId, let videoTrack = videoTrack as? LocalCameraVideoTrack { videoTrack.switchCamera(deviceId: captureDeviceId) @@ -215,9 +213,7 @@ public class MembraneRTC: MulticastDelegate, ObservableObje DispatchQueue.webRTC.sync { let audioTrack = LocalAudioTrack(peerConnectionFactoryWrapper: peerConnectionFactoryWrapper) - if state == .connected { - peerConnectionManager.addTrack(track: audioTrack, localStreamId: localStreamId) - } + peerConnectionManager.addTrack(track: audioTrack, localStreamId: localStreamId) audioTrack.start() diff --git a/Sources/MembraneRTC/PeerConnectionManager.swift b/Sources/MembraneRTC/PeerConnectionManager.swift index 64f64a5b..7df67667 100644 --- a/Sources/MembraneRTC/PeerConnectionManager.swift +++ b/Sources/MembraneRTC/PeerConnectionManager.swift @@ -177,7 +177,6 @@ internal class PeerConnectionManager: NSObject, RTCPeerConnectionDelegate { public func addTrack(track: LocalTrack, localStreamId: String) { guard let pc = connection else { - sdkLogger.error("\(#function): Peer connection not yet established") return } From 2745f2598dad0e5a27f7906a6e687b92dd10e7ac Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Thu, 22 Jun 2023 14:48:25 +0200 Subject: [PATCH 8/8] Fix memory leak (#43) --- Sources/MembraneRTC/UI/VideoView.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Sources/MembraneRTC/UI/VideoView.swift b/Sources/MembraneRTC/UI/VideoView.swift index f427e4c5..11997137 100644 --- a/Sources/MembraneRTC/UI/VideoView.swift +++ b/Sources/MembraneRTC/UI/VideoView.swift @@ -86,6 +86,14 @@ public class VideoView: UIView { } } + deinit { + if let rendererView = rendererView, + let rtcVideoTrack = track?.rtcTrack() as? RTCVideoTrack + { + rtcVideoTrack.remove(rendererView) + } + } + /// Delegate listening for the view's changes such as dimensions. public weak var delegate: VideoViewDelegate?