Skip to content

Commit

Permalink
Make LocalParticipant non-Optional (#272)
Browse files Browse the repository at this point in the history
* impl

* identity and name are optional
  • Loading branch information
hiroshihorie authored Nov 6, 2023
1 parent 36a7d34 commit 3a07312
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 97 deletions.
2 changes: 1 addition & 1 deletion Sources/LiveKit/Core/Engine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ extension Engine {

try await signalClient.sendSyncState(answer: previousAnswer.toPBType(),
offer: previousOffer?.toPBType(),
subscription: subscription, publishTracks: room._state.localParticipant?.publishedTracksInfo(),
subscription: subscription, publishTracks: room.localParticipant.publishedTracksInfo(),
dataChannels: publisherDC.infos())
}
}
Expand Down
4 changes: 1 addition & 3 deletions Sources/LiveKit/Core/Room+Convenience.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ import Foundation
public extension Room {
var allParticipants: [Sid: Participant] {
var result: [Sid: Participant] = remoteParticipants

if let localParticipant {
if !localParticipant.sid.isEmpty {
result.updateValue(localParticipant, forKey: localParticipant.sid)
}

return result
}
}
8 changes: 3 additions & 5 deletions Sources/LiveKit/Core/Room+EngineDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ extension Room: EngineDelegate {
}

// Re-send track permissions
if case .connected = state.connectionState, let localParticipant {
if case .connected = state.connectionState {
Task {
do {
try await localParticipant.sendTrackSubscriptionPermissions()
Expand Down Expand Up @@ -82,9 +82,7 @@ extension Room: EngineDelegate {
var seenSids = [String: Bool]()
for speaker in speakers {
seenSids[speaker.sid] = true
if let localParticipant = state.localParticipant,
speaker.sid == localParticipant.sid
{
if speaker.sid == localParticipant.sid {
localParticipant._state.mutate {
$0.audioLevel = speaker.level
$0.isSpeaking = true
Expand All @@ -101,7 +99,7 @@ extension Room: EngineDelegate {
}
}

if let localParticipant = state.localParticipant, seenSids[localParticipant.sid] == nil {
if seenSids[localParticipant.sid] == nil {
localParticipant._state.mutate {
$0.audioLevel = 0.0
$0.isSpeaking = false
Expand Down
21 changes: 7 additions & 14 deletions Sources/LiveKit/Core/Room+SignalClientDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ extension Room: SignalClientDelegate {
func signalClient(_: SignalClient, didUpdate trackSid: String, subscribedQualities: [Livekit_SubscribedQuality]) {
log("qualities: \(subscribedQualities.map { String(describing: $0) }.joined(separator: ", "))")

guard let localParticipant = _state.localParticipant else { return }
localParticipant.onSubscribedQualitiesUpdate(trackSid: trackSid, subscribedQualities: subscribedQualities)
}

Expand All @@ -55,9 +54,7 @@ extension Room: SignalClientDelegate {
$0.serverRegion = joinResponse.serverRegion.isEmpty ? nil : joinResponse.serverRegion
$0.isRecording = joinResponse.room.activeRecording

if joinResponse.hasParticipant {
$0.localParticipant = LocalParticipant(from: joinResponse.participant, room: self)
}
localParticipant.updateFromInfo(info: joinResponse.participant)

if !joinResponse.otherParticipants.isEmpty {
for otherParticipant in joinResponse.otherParticipants {
Expand All @@ -84,7 +81,7 @@ extension Room: SignalClientDelegate {

var lastSpeakers = state.activeSpeakers.reduce(into: [Sid: Participant]()) { $0[$1.sid] = $1 }
for speaker in speakers {
guard let participant = speaker.sid == state.localParticipant?.sid ? state.localParticipant : state.remoteParticipants[speaker.sid] else {
guard let participant = speaker.sid == localParticipant.sid ? localParticipant : state.remoteParticipants[speaker.sid] else {
continue
}

Expand Down Expand Up @@ -118,9 +115,7 @@ extension Room: SignalClientDelegate {
log("connectionQuality: \(connectionQuality)", .trace)

for entry in connectionQuality {
if let localParticipant = _state.localParticipant,
entry.participantSid == localParticipant.sid
{
if entry.participantSid == localParticipant.sid {
// update for LocalParticipant
localParticipant._state.mutate { $0.connectionQuality = entry.quality.toLKType() }
} else if let participant = _state.remoteParticipants[entry.participantSid] {
Expand All @@ -133,7 +128,7 @@ extension Room: SignalClientDelegate {
func signalClient(_: SignalClient, didUpdateRemoteMute trackSid: String, muted: Bool) {
log("trackSid: \(trackSid) muted: \(muted)")

guard let publication = _state.localParticipant?._state.tracks[trackSid] as? LocalTrackPublication else {
guard let publication = localParticipant._state.tracks[trackSid] as? LocalTrackPublication else {
// publication was not found but the delegate was handled
return
}
Expand Down Expand Up @@ -180,8 +175,8 @@ extension Room: SignalClientDelegate {

_state.mutate {
for info in participants {
if info.sid == $0.localParticipant?.sid {
$0.localParticipant?.updateFromInfo(info: info)
if info.sid == localParticipant.sid {
localParticipant.updateFromInfo(info: info)
continue
}

Expand Down Expand Up @@ -221,9 +216,7 @@ extension Room: SignalClientDelegate {
func signalClient(_: SignalClient, didUnpublish localTrack: Livekit_TrackUnpublishedResponse) {
log()

guard let localParticipant,
let publication = localParticipant._state.tracks[localTrack.trackSid] as? LocalTrackPublication
else {
guard let publication = localParticipant._state.tracks[localTrack.trackSid] as? LocalTrackPublication else {
log("track publication not found", .warning)
return
}
Expand Down
19 changes: 4 additions & 15 deletions Sources/LiveKit/Core/Room.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ public class Room: NSObject, ObservableObject, Loggable {
@objc
public var serverRegion: String? { _state.serverRegion }

@objc
public var localParticipant: LocalParticipant? { _state.localParticipant }

@objc
public var remoteParticipants: [Sid: RemoteParticipant] { _state.remoteParticipants }

Expand Down Expand Up @@ -93,6 +90,9 @@ public class Room: NSObject, ObservableObject, Loggable {

public var e2eeManager: E2EEManager?

@objc
public lazy var localParticipant: LocalParticipant = .init(room: self)

struct State: Equatable {
var options: RoomOptions

Expand All @@ -102,7 +102,6 @@ public class Room: NSObject, ObservableObject, Loggable {
var serverVersion: String?
var serverRegion: String?

var localParticipant: LocalParticipant?
var remoteParticipants = [Sid: RemoteParticipant]()
var activeSpeakers = [Participant]()

Expand Down Expand Up @@ -220,11 +219,6 @@ public class Room: NSObject, ObservableObject, Loggable {

let state = _state.copy()

guard state.localParticipant == nil else {
log("localParticipant is not nil", .warning)
throw EngineError.state(message: "localParticipant is not nil")
}

// update options if specified
if let roomOptions, roomOptions != state.options {
_state.mutate { $0.options = roomOptions }
Expand All @@ -238,7 +232,7 @@ public class Room: NSObject, ObservableObject, Loggable {

try await engine.connect(url, token, connectOptions: connectOptions)

log("Connected to \(String(describing: self)) \(String(describing: state.localParticipant))", .info)
log("Connected to \(String(describing: self))", .info)
}

@objc
Expand Down Expand Up @@ -310,7 +304,6 @@ extension Room {
}

_state.mutate {
$0.localParticipant = nil
$0.remoteParticipants = [:]
}
}
Expand Down Expand Up @@ -356,8 +349,6 @@ extension Room: AppStateDelegate {
func appDidEnterBackground() {
guard _state.options.suspendLocalVideoTracksInBackground else { return }

guard let localParticipant else { return }

let cameraVideoTracks = localParticipant.localVideoTracks.filter { $0.source == .camera }

guard !cameraVideoTracks.isEmpty else { return }
Expand All @@ -374,8 +365,6 @@ extension Room: AppStateDelegate {
}

func appWillEnterForeground() {
guard let localParticipant else { return }

let cameraVideoTracks = localParticipant.localVideoTracks.filter { $0.source == .camera }

guard !cameraVideoTracks.isEmpty else { return }
Expand Down
42 changes: 21 additions & 21 deletions Sources/LiveKit/E2EE/E2EEManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,30 +63,30 @@ public class E2EEManager: NSObject, ObservableObject, Loggable {
}
self.room = room
self.room?.delegates.add(delegate: self)
self.room?.localParticipant?.tracks.forEach { (_: Sid, publication: TrackPublication) in
self.room?.localParticipant.tracks.forEach { (_: Sid, publication: TrackPublication) in
if publication.encryptionType == EncryptionType.none {
self.log("E2EEManager::setup: local participant \(self.room!.localParticipant!.identity) track \(publication.sid) encryptionType is none, skip")
self.log("E2EEManager::setup: local participant \(self.room!.localParticipant.sid) track \(publication.sid) encryptionType is none, skip")
return
}
if publication.track?.rtpSender == nil {
self.log("E2EEManager::setup: publication.track?.rtpSender is nil, skip to create FrameCryptor!")
return
}
let fc = addRtpSender(sender: publication.track!.rtpSender!, participantId: self.room!.localParticipant!.identity, trackSid: publication.sid)
let fc = addRtpSender(sender: publication.track!.rtpSender!, participantSid: self.room!.localParticipant.sid, trackSid: publication.sid)
trackPublications[fc] = publication
}

self.room?.remoteParticipants.forEach { (_: Sid, participant: RemoteParticipant) in
participant.tracks.forEach { (_: Sid, publication: TrackPublication) in
if publication.encryptionType == EncryptionType.none {
self.log("E2EEManager::setup: remote participant \(participant.identity) track \(publication.sid) encryptionType is none, skip")
self.log("E2EEManager::setup: remote participant \(participant.sid) track \(publication.sid) encryptionType is none, skip")
return
}
if publication.track?.rtpReceiver == nil {
self.log("E2EEManager::setup: publication.track?.rtpReceiver is nil, skip to create FrameCryptor!")
return
}
let fc = addRtpReceiver(receiver: publication.track!.rtpReceiver!, participantId: participant.identity, trackSid: publication.sid)
let fc = addRtpReceiver(receiver: publication.track!.rtpReceiver!, participantSid: participant.sid, trackSid: publication.sid)
trackPublications[fc] = publication
}
}
Expand All @@ -99,20 +99,20 @@ public class E2EEManager: NSObject, ObservableObject, Loggable {
}
}

func addRtpSender(sender: LKRTCRtpSender, participantId: String, trackSid: Sid) -> LKRTCFrameCryptor {
log("addRtpSender \(participantId) to E2EEManager")
let frameCryptor = LKRTCFrameCryptor(factory: Engine.peerConnectionFactory, rtpSender: sender, participantId: participantId, algorithm: RTCCyrptorAlgorithm.aesGcm, keyProvider: e2eeOptions.keyProvider.rtcKeyProvider!)
func addRtpSender(sender: LKRTCRtpSender, participantSid: String, trackSid: Sid) -> LKRTCFrameCryptor {
log("addRtpSender \(participantSid) to E2EEManager")
let frameCryptor = LKRTCFrameCryptor(factory: Engine.peerConnectionFactory, rtpSender: sender, participantId: participantSid, algorithm: RTCCyrptorAlgorithm.aesGcm, keyProvider: e2eeOptions.keyProvider.rtcKeyProvider!)
frameCryptor.delegate = delegateAdapter
frameCryptors[[participantId: trackSid]] = frameCryptor
frameCryptors[[participantSid: trackSid]] = frameCryptor
frameCryptor.enabled = enabled
return frameCryptor
}

func addRtpReceiver(receiver: LKRTCRtpReceiver, participantId: String, trackSid: Sid) -> LKRTCFrameCryptor {
log("addRtpReceiver \(participantId) to E2EEManager")
let frameCryptor = LKRTCFrameCryptor(factory: Engine.peerConnectionFactory, rtpReceiver: receiver, participantId: participantId, algorithm: RTCCyrptorAlgorithm.aesGcm, keyProvider: e2eeOptions.keyProvider.rtcKeyProvider!)
func addRtpReceiver(receiver: LKRTCRtpReceiver, participantSid: String, trackSid: Sid) -> LKRTCFrameCryptor {
log("addRtpReceiver \(participantSid) to E2EEManager")
let frameCryptor = LKRTCFrameCryptor(factory: Engine.peerConnectionFactory, rtpReceiver: receiver, participantId: participantSid, algorithm: RTCCyrptorAlgorithm.aesGcm, keyProvider: e2eeOptions.keyProvider.rtcKeyProvider!)
frameCryptor.delegate = delegateAdapter
frameCryptors[[participantId: trackSid]] = frameCryptor
frameCryptors[[participantSid: trackSid]] = frameCryptor
frameCryptor.enabled = enabled
return frameCryptor
}
Expand Down Expand Up @@ -148,25 +148,25 @@ extension E2EEManager {
extension E2EEManager: RoomDelegate {
public func room(_: Room, localParticipant: LocalParticipant, didPublish publication: LocalTrackPublication) {
if publication.encryptionType == EncryptionType.none {
log("E2EEManager::RoomDelegate: local participant \(localParticipant.identity) track \(publication.sid) encryptionType is none, skip")
log("E2EEManager::RoomDelegate: local participant \(String(describing: localParticipant.sid)) track \(publication.sid) encryptionType is none, skip")
return
}
if publication.track?.rtpSender == nil {
log("E2EEManager::RoomDelegate: publication.track?.rtpSender is nil, skip to create FrameCryptor!")
return
}
let fc = addRtpSender(sender: publication.track!.rtpSender!, participantId: localParticipant.identity, trackSid: publication.sid)
let fc = addRtpSender(sender: publication.track!.rtpSender!, participantSid: localParticipant.sid, trackSid: publication.sid)
trackPublications[fc] = publication
}

public func room(_: Room, localParticipant: LocalParticipant, didUnpublish publication: LocalTrackPublication) {
let frameCryptor = frameCryptors.first(where: { (key: [String: Sid], _: LKRTCFrameCryptor) -> Bool in
key[localParticipant.identity] == publication.sid
key[localParticipant.sid] == publication.sid
})?.value

frameCryptor?.delegate = nil
frameCryptor?.enabled = false
frameCryptors.removeValue(forKey: [localParticipant.identity: publication.sid])
frameCryptors.removeValue(forKey: [localParticipant.sid: publication.sid])

if frameCryptor != nil {
trackPublications.removeValue(forKey: frameCryptor!)
Expand All @@ -175,25 +175,25 @@ extension E2EEManager: RoomDelegate {

public func room(_: Room, participant: RemoteParticipant, didSubscribe publication: RemoteTrackPublication, track _: Track) {
if publication.encryptionType == EncryptionType.none {
log("E2EEManager::RoomDelegate: remote participant \(participant.identity) track \(publication.sid) encryptionType is none, skip")
log("E2EEManager::RoomDelegate: remote participant \(String(describing: participant.sid)) track \(publication.sid) encryptionType is none, skip")
return
}
if publication.track?.rtpReceiver == nil {
log("E2EEManager::RoomDelegate: publication.track?.rtpReceiver is nil, skip to create FrameCryptor!")
return
}
let fc = addRtpReceiver(receiver: publication.track!.rtpReceiver!, participantId: participant.identity, trackSid: publication.sid)
let fc = addRtpReceiver(receiver: publication.track!.rtpReceiver!, participantSid: participant.sid, trackSid: publication.sid)
trackPublications[fc] = publication
}

public func room(_: Room, participant: RemoteParticipant, didUnsubscribe publication: RemoteTrackPublication, track _: Track) {
let frameCryptor = frameCryptors.first(where: { (key: [String: Sid], _: LKRTCFrameCryptor) -> Bool in
key[participant.identity] == publication.sid
key[participant.sid] == publication.sid
})?.value

frameCryptor?.delegate = nil
frameCryptor?.enabled = false
frameCryptors.removeValue(forKey: [participant.identity: publication.sid])
frameCryptors.removeValue(forKey: [participant.sid: publication.sid])

if frameCryptor != nil {
trackPublications.removeValue(forKey: frameCryptor!)
Expand Down
13 changes: 3 additions & 10 deletions Sources/LiveKit/Participant/LocalParticipant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,8 @@ public class LocalParticipant: Participant {
private var allParticipantsAllowed: Bool = true
private var trackPermissions: [ParticipantTrackPermission] = []

convenience init(from info: Livekit_ParticipantInfo,
room: Room)
{
self.init(sid: info.sid,
identity: info.identity,
name: info.name,
room: room)

updateFromInfo(info: info)
init(room: Room) {
super.init(sid: "", room: room)
}

func getTrackPublication(sid: Sid) -> LocalTrackPublication? {
Expand Down Expand Up @@ -321,7 +314,7 @@ public class LocalParticipant: Participant {

// TODO: Revert internal state on failure

try await room.engine.signalClient.sendUpdateLocalMetadata(metadata, name: name)
try await room.engine.signalClient.sendUpdateLocalMetadata(metadata, name: name ?? "")
}

/// Sets and updates the name of the local participant.
Expand Down
Loading

0 comments on commit 3a07312

Please sign in to comment.