Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2 API changes #280

Merged
merged 8 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rename this to publishData, too, so that it's easier to refer to the same API in the docs?

reliability: Reliability = .reliable,
destinations: [Sid]? = nil,
destinationIdentities: [Identity]? = nil,
topic: String? = nil,
options: DataPublishOptions? = nil) async throws
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to simplify the API here, could we give publishData(data, options?) as the only parameters?

{
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 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: in the JS version this is called trackPublications with the plural s only on publications. I think it would be good to align this across platforms

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, this is a refactoring typo


@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