Skip to content

Commit

Permalink
v2 API changes (#280)
Browse files Browse the repository at this point in the history
  • Loading branch information
hiroshihorie authored Dec 6, 2023
1 parent 6ee16e9 commit 5bf6799
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 78 deletions.
13 changes: 9 additions & 4 deletions Sources/LiveKit/Core/Room+EngineDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ extension Room: EngineDelegate {
}
activeSpeakers.append(localParticipant)
} else {
if let participant = state.remoteParticipants[speaker.sid] {
if let participant = state.remoteParticipant(sid: speaker.sid) {
participant._state.mutate {
$0.audioLevel = speaker.level
$0.isSpeaking = true
Expand Down Expand Up @@ -140,9 +140,14 @@ extension Room: EngineDelegate {
trackSid = track.trackId
}

let participant = _state.mutate { $0.getOrCreateRemoteParticipant(sid: participantSid, room: self) }
let participant = _state.read {
$0.remoteParticipants.values.first { $0.sid == participantSid }
}

log("added media track from: \(participantSid), sid: \(trackSid)")
guard let participant else {
log("RemoteParticipant not found for sid: \(participantSid), remoteParticipants: \(remoteParticipants)", .warning)
return
}

let task = Task.retrying(retryDelay: 0.2) { _, _ in
// TODO: Only retry for TrackError.state = error
Expand All @@ -163,7 +168,7 @@ extension Room: EngineDelegate {

func engine(_ engine: Engine, didReceive userPacket: Livekit_UserPacket) {
// participant could be null if data broadcasted from server
let participant = _state.remoteParticipants[userPacket.participantSid]
let participant = _state.remoteParticipants[userPacket.participantIdentity]

engine.executeIfConnected { [weak self] in
guard let self else { return }
Expand Down
20 changes: 10 additions & 10 deletions Sources/LiveKit/Core/Room+SignalClientDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension Room: SignalClientDelegate {

if !joinResponse.otherParticipants.isEmpty {
for otherParticipant in joinResponse.otherParticipants {
$0.getOrCreateRemoteParticipant(sid: otherParticipant.sid, info: otherParticipant, room: self)
$0.updateRemoteParticipant(info: otherParticipant, room: self)
}
}
}
Expand All @@ -105,7 +105,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 == localParticipant.sid ? localParticipant : state.remoteParticipants[speaker.sid] else {
guard let participant = speaker.sid == localParticipant.sid ? localParticipant : state.remoteParticipant(sid: speaker.sid) else {
continue
}

Expand Down Expand Up @@ -142,7 +142,7 @@ extension Room: SignalClientDelegate {
if entry.participantSid == localParticipant.sid {
// update for LocalParticipant
localParticipant._state.mutate { $0.connectionQuality = entry.quality.toLKType() }
} else if let participant = _state.remoteParticipants[entry.participantSid] {
} else if let participant = _state.read({ $0.remoteParticipant(sid: entry.participantSid) }) {
// udpate for RemoteParticipant
participant._state.mutate { $0.connectionQuality = entry.quality.toLKType() }
}
Expand All @@ -169,7 +169,7 @@ extension Room: SignalClientDelegate {
func signalClient(_: SignalClient, didUpdateSubscriptionPermission subscriptionPermission: Livekit_SubscriptionPermissionUpdate) {
log("did update subscriptionPermission: \(subscriptionPermission)")

guard let participant = _state.remoteParticipants[subscriptionPermission.participantSid],
guard let participant = _state.read({ $0.remoteParticipant(sid: subscriptionPermission.participantSid) }),
let publication = participant.getTrackPublication(sid: subscriptionPermission.trackSid)
else {
return
Expand All @@ -194,7 +194,7 @@ extension Room: SignalClientDelegate {
func signalClient(_: SignalClient, didUpdateParticipants participants: [Livekit_ParticipantInfo]) {
log("participants: \(participants)")

var disconnectedParticipants = [Sid]()
var disconnectedParticipantIdentities = [Identity]()
var newParticipants = [RemoteParticipant]()

_state.mutate {
Expand All @@ -206,10 +206,10 @@ extension Room: SignalClientDelegate {

if info.state == .disconnected {
// when it's disconnected, send updates
disconnectedParticipants.append(info.sid)
disconnectedParticipantIdentities.append(info.identity)
} else {
let isNewParticipant = $0.remoteParticipants[info.sid] == nil
let participant = $0.getOrCreateRemoteParticipant(sid: info.sid, info: info, room: self)
let isNewParticipant = $0.remoteParticipant(sid: info.sid) == nil
let participant = $0.updateRemoteParticipant(info: info, room: self)

if isNewParticipant {
newParticipants.append(participant)
Expand All @@ -220,9 +220,9 @@ extension Room: SignalClientDelegate {
}
}

for sid in disconnectedParticipants {
for identity in disconnectedParticipantIdentities {
Task {
try await onParticipantDisconnect(sid: sid)
try await _onParticipantDidDisconnect(identity: identity)
}
}

Expand Down
31 changes: 17 additions & 14 deletions Sources/LiveKit/Core/Room.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class Room: NSObject, ObservableObject, Loggable {
public var serverNodeId: String? { _state.serverInfo?.nodeID.nilIfEmpty }

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

@objc
public var activeSpeakers: [Participant] { _state.activeSpeakers }
Expand Down Expand Up @@ -102,7 +102,7 @@ public class Room: NSObject, ObservableObject, Loggable {
var name: String?
var metadata: String?

var remoteParticipants = [Sid: RemoteParticipant]()
var remoteParticipants = [Identity: RemoteParticipant]()
var activeSpeakers = [Participant]()

var isRecording: Bool = false
Expand All @@ -114,15 +114,19 @@ public class Room: NSObject, ObservableObject, Loggable {
var serverInfo: Livekit_ServerInfo?

@discardableResult
mutating func getOrCreateRemoteParticipant(sid: Sid, info: Livekit_ParticipantInfo? = nil, room: Room) -> RemoteParticipant {
if let participant = remoteParticipants[sid] {
return participant
}

let participant = RemoteParticipant(sid: sid, info: info, room: room)
remoteParticipants[sid] = participant
mutating func updateRemoteParticipant(info: Livekit_ParticipantInfo, room: Room) -> RemoteParticipant {
// Check if RemoteParticipant with same identity exists...
if let participant = remoteParticipants[info.identity] { return participant }
// Create new RemoteParticipant...
let participant = RemoteParticipant(info: info, room: room)
remoteParticipants[info.identity] = participant
return participant
}

// Find RemoteParticipant by Sid
func remoteParticipant(sid: Sid) -> RemoteParticipant? {
remoteParticipants.values.first(where: { $0.sid == sid })
}
}

var _state: StateSync<State>
Expand Down Expand Up @@ -296,8 +300,7 @@ extension Room {
log("notify: \(_notify)")

// Stop all local & remote tracks
let allParticipants = ([[localParticipant],
_state.remoteParticipants.map(\.value)] as [[Participant?]])
let allParticipants = ([[localParticipant], Array(_state.remoteParticipants.values)] as [[Participant?]])
.joined()
.compactMap { $0 }

Expand All @@ -310,9 +313,9 @@ extension Room {
}
}

func onParticipantDisconnect(sid: Sid) async throws {
guard let participant = _state.mutate({ $0.remoteParticipants.removeValue(forKey: sid) }) else {
throw EngineError.state(message: "Participant not found for \(sid)")
func _onParticipantDidDisconnect(identity: Identity) async throws {
guard let participant = _state.mutate({ $0.remoteParticipants.removeValue(forKey: identity) }) else {
throw EngineError.state(message: "Participant not found for \(identity)")
}

await participant.cleanUp(notify: true)
Expand Down
6 changes: 3 additions & 3 deletions Sources/LiveKit/E2EE/E2EEManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ 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.tracksPublications.values.forEach { (publication: TrackPublication) in
if publication.encryptionType == EncryptionType.none {
self.log("E2EEManager::setup: local participant \(self.room!.localParticipant.sid) track \(publication.sid) encryptionType is none, skip")
return
Expand All @@ -76,8 +76,8 @@ public class E2EEManager: NSObject, ObservableObject, Loggable {
trackPublications[fc] = publication
}

self.room?.remoteParticipants.forEach { (_: Sid, participant: RemoteParticipant) in
participant.tracks.forEach { (_: Sid, publication: TrackPublication) in
self.room?.remoteParticipants.values.forEach { (participant: RemoteParticipant) in
participant.tracksPublications.values.forEach { (publication: TrackPublication) in
if publication.encryptionType == EncryptionType.none {
self.log("E2EEManager::setup: remote participant \(participant.sid) track \(publication.sid) encryptionType is none, skip")
return
Expand Down
28 changes: 0 additions & 28 deletions Sources/LiveKit/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,6 @@

import Foundation

class Identity {
let identity: String
let publish: String?

init(identity: String,
publish: String?)
{
self.identity = identity
self.publish = publish
}
}

extension Livekit_ParticipantInfo {
// parses identity string for the &publish= param of identity
func parseIdentity() -> Identity {
let segments = identity.split(separator: "#", maxSplits: 1)
var publishSegment: String?
if segments.count >= 2 {
publishSegment = String(segments[1])
}

return Identity(
identity: String(segments[0]),
publish: publishSegment
)
}
}

extension String {
/// Simply return nil if String is empty
var nilIfEmpty: String? {
Expand Down
6 changes: 3 additions & 3 deletions Sources/LiveKit/Participant/LocalParticipant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class LocalParticipant: Participant {
private var trackPermissions: [ParticipantTrackPermission] = []

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

func getTrackPublication(sid: Sid) -> LocalTrackPublication? {
Expand Down Expand Up @@ -307,7 +307,7 @@ public class LocalParticipant: Participant {
@objc
public func publish(data: Data,
reliability: Reliability = .reliable,
destinations: [Sid]? = nil,
destinationIdentities: [Identity]? = nil,
topic: String? = nil,
options: DataPublishOptions? = nil) async throws
{
Expand All @@ -316,7 +316,7 @@ public class LocalParticipant: Participant {
let userPacket = Livekit_UserPacket.with {
$0.participantSid = self.sid
$0.payload = data
$0.destinationSids = destinations ?? options.destinations
$0.destinationIdentities = destinationIdentities ?? options.destinationIdentities
$0.topic = topic ?? options.topic ?? ""
}

Expand Down
12 changes: 6 additions & 6 deletions Sources/LiveKit/Participant/Participant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class Participant: NSObject, ObservableObject, Loggable {
public var sid: Sid { _state.sid }

@objc
public var identity: String? { _state.identity }
public var identity: String { _state.identity }

@objc
public var name: String? { _state.name }
Expand All @@ -53,7 +53,7 @@ public class Participant: NSObject, ObservableObject, Loggable {
public var joinedAt: Date? { _state.joinedAt }

@objc
public var tracks: [String: TrackPublication] { _state.tracks }
public var tracksPublications: [Sid: TrackPublication] { _state.tracks }

@objc
public var audioTracks: [TrackPublication] {
Expand All @@ -74,7 +74,7 @@ public class Participant: NSObject, ObservableObject, Loggable {

struct State: Equatable, Hashable {
var sid: Sid
var identity: String?
var identity: String
var name: String?
var audioLevel: Float = 0.0
var isSpeaking: Bool = false
Expand All @@ -87,11 +87,11 @@ public class Participant: NSObject, ObservableObject, Loggable {

var _state: StateSync<State>

init(sid: String, room: Room) {
init(sid: Sid, identity: Identity, room: Room) {
self.room = room

// initial state
_state = StateSync(State(sid: sid))
_state = StateSync(State(sid: sid, identity: identity))

super.init()

Expand Down Expand Up @@ -153,7 +153,7 @@ public class Participant: NSObject, ObservableObject, Loggable {
func cleanUp(notify _notify: Bool = true) async {
await unpublishAll(notify: _notify)
// Reset state
_state.mutate { $0 = State(sid: "") }
_state.mutate { $0 = State(sid: "", identity: "") }
}

func unpublishAll(notify _: Bool = true) async {
Expand Down
12 changes: 8 additions & 4 deletions Sources/LiveKit/Participant/RemoteParticipant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import Foundation

@objc
public class RemoteParticipant: Participant {
init(sid: Sid, info: Livekit_ParticipantInfo?, room: Room) {
super.init(sid: sid, room: room)
init(info: Livekit_ParticipantInfo, room: Room) {
super.init(sid: info.sid,
identity: info.identity,
room: room)

if let info {
updateFromInfo(info: info)
if identity.isEmpty {
log("RemoteParticipant.identity is empty", .error)
}

updateFromInfo(info: info)
}

func getTrackPublication(sid: Sid) -> RemoteTrackPublication? {
Expand Down
10 changes: 5 additions & 5 deletions Sources/LiveKit/Types/Options/DataPublishOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ public class DataPublishOptions: NSObject, PublishOptions {
public let name: String?

@objc
public let destinations: [Sid]
public let destinationIdentities: [Identity]

@objc
public let topic: String?

public init(name: String? = nil,
destinations: [String] = [],
destinationIdentities: [Identity] = [],
topic: String? = nil)
{
self.name = name
self.destinations = destinations
self.destinationIdentities = destinationIdentities
self.topic = topic
}

Expand All @@ -41,14 +41,14 @@ public class DataPublishOptions: NSObject, PublishOptions {
override public func isEqual(_ object: Any?) -> Bool {
guard let other = object as? Self else { return false }
return name == other.name &&
destinations == other.destinations &&
destinationIdentities == other.destinationIdentities &&
topic == other.topic
}

override public var hash: Int {
var hasher = Hasher()
hasher.combine(name)
hasher.combine(destinations)
hasher.combine(destinationIdentities)
hasher.combine(topic)
return hasher.finalize()
}
Expand Down
1 change: 1 addition & 0 deletions Sources/LiveKit/Types/Other.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Foundation
@_implementationOnly import WebRTC

public typealias Sid = String
public typealias Identity = String

@objc
public enum Reliability: Int {
Expand Down
2 changes: 1 addition & 1 deletion Sources/LiveKit/Views/VideoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ public class VideoView: NativeView, Loggable {

// dimensions are required to continue computation
guard let dimensions = track._state.dimensions else {
log("dimensions are nil, cannot layout without dimensions, track: \(track)", .warning)
// log("dimensions are nil, cannot layout without dimensions, track: \(track)", .debug)
return
}

Expand Down

0 comments on commit 5bf6799

Please sign in to comment.