diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index a6e45db008..dc0241b47c 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -57,7 +57,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { groupCall: nil ))) - self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", peerIds: [], limit: 100) + self.disposable = (getGroupCallParticipants(account: account, callId: call.id, accessHash: call.accessHash, offset: "", ssrcs: [], limit: 100) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) @@ -228,13 +228,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { private let silentTimeout: Int32 = 2 struct Participant { + let ssrc: UInt32 let timestamp: Int32 let level: Float } private var participants: [PeerId: Participant] = [:] - private let speakingParticipantsPromise = ValuePromise>() - private var speakingParticipants = Set() { + private let speakingParticipantsPromise = ValuePromise<[PeerId: UInt32]>() + private var speakingParticipants = [PeerId: UInt32]() { didSet { self.speakingParticipantsPromise.set(self.speakingParticipants) } @@ -245,17 +246,17 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { init() { } - func update(levels: [(PeerId, Float, Bool)]) { + func update(levels: [(PeerId, UInt32, Float, Bool)]) { let timestamp = Int32(CFAbsoluteTimeGetCurrent()) let currentParticipants: [PeerId: Participant] = self.participants var validSpeakers: [PeerId: Participant] = [:] var silentParticipants = Set() - var speakingParticipants = Set() - for (peerId, level, hasVoice) in levels { + var speakingParticipants = [PeerId: UInt32]() + for (peerId, ssrc, level, hasVoice) in levels { if level > speakingLevelThreshold && hasVoice { - validSpeakers[peerId] = Participant(timestamp: timestamp, level: level) - speakingParticipants.insert(peerId) + validSpeakers[peerId] = Participant(ssrc: ssrc, timestamp: timestamp, level: level) + speakingParticipants[peerId] = ssrc } else { silentParticipants.insert(peerId) } @@ -268,17 +269,17 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { if silentParticipants.contains(peerId) { if delta < silentTimeout { validSpeakers[peerId] = participant - speakingParticipants.insert(peerId) + speakingParticipants[peerId] = participant.ssrc } } else if delta < cutoffTimeout { validSpeakers[peerId] = participant - speakingParticipants.insert(peerId) + speakingParticipants[peerId] = participant.ssrc } } } var audioLevels: [(PeerId, Float, Bool)] = [] - for (peerId, level, hasVoice) in levels { + for (peerId, _, level, hasVoice) in levels { if level > 0.001 { audioLevels.append((peerId, level, hasVoice)) } @@ -289,8 +290,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.audioLevelsPromise.set(.single(audioLevels)) } - func get() -> Signal, NoError> { - return self.speakingParticipantsPromise.get() |> distinctUntilChanged + func get() -> Signal<[PeerId: UInt32], NoError> { + return self.speakingParticipantsPromise.get() } func getAudioLevels() -> Signal<[(PeerId, Float, Bool)], NoError> { @@ -887,16 +888,19 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { guard let strongSelf = self else { return } - var result: [(PeerId, Float, Bool)] = [] + var result: [(PeerId, UInt32, Float, Bool)] = [] var myLevel: Float = 0.0 var myLevelHasVoice: Bool = false for (ssrcKey, level, hasVoice) in levels { var peerId: PeerId? + let ssrcValue: UInt32 switch ssrcKey { case .local: peerId = strongSelf.accountContext.account.peerId + ssrcValue = 0 case let .source(ssrc): peerId = strongSelf.ssrcMapping[ssrc] + ssrcValue = ssrc } if let peerId = peerId { if case .local = ssrcKey { @@ -905,7 +909,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { myLevelHasVoice = hasVoice } } - result.append((peerId, level, hasVoice)) + result.append((peerId, ssrcValue, level, hasVoice)) } } @@ -985,9 +989,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { var topParticipants: [GroupCallParticipantsContext.Participant] = [] - var reportSpeakingParticipants: [PeerId] = [] + var reportSpeakingParticipants: [PeerId: UInt32] = [:] let timestamp = CACurrentMediaTime() - for peerId in speakingParticipants { + for (peerId, ssrc) in speakingParticipants { let shouldReport: Bool if let previousTimestamp = strongSelf.speakingParticipantsReportTimestamp[peerId] { shouldReport = previousTimestamp + 1.0 < timestamp @@ -996,7 +1000,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } if shouldReport { strongSelf.speakingParticipantsReportTimestamp[peerId] = timestamp - reportSpeakingParticipants.append(peerId) + reportSpeakingParticipants[peerId] = ssrc } } @@ -1008,7 +1012,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { var members = PresentationGroupCallMembers( participants: [], - speakingParticipants: speakingParticipants, + speakingParticipants: Set(speakingParticipants.keys), totalCount: 0, loadMoreToken: nil ) diff --git a/submodules/TelegramCore/Sources/GroupCalls.swift b/submodules/TelegramCore/Sources/GroupCalls.swift index 8a02f438c9..6790be8fe5 100644 --- a/submodules/TelegramCore/Sources/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/GroupCalls.swift @@ -187,8 +187,8 @@ public enum GetGroupCallParticipantsError { case generic } -public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, peerIds: [PeerId], limit: Int32) -> Signal { - return account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), ids: peerIds.map { $0.id }, sources: [], offset: offset, limit: limit)) +public func getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32) -> Signal { + return account.network.request(Api.functions.phone.getGroupParticipants(call: .inputGroupCall(id: callId, accessHash: accessHash), ids: [], sources: ssrcs.map { Int32(bitPattern: $0) }, offset: offset, limit: limit)) |> mapError { _ -> GetGroupCallParticipantsError in return .generic } @@ -368,7 +368,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, callId: Int64, acces |> mapError { _ -> JoinGroupCallError in return .generic }, - getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", peerIds: [], limit: 100) + getGroupCallParticipants(account: account, callId: callId, accessHash: accessHash, offset: "", ssrcs: [], limit: 100) |> mapError { _ -> JoinGroupCallError in return .generic }, @@ -772,7 +772,7 @@ public final class GroupCallParticipantsContext { private var isLoadingMore: Bool = false private var shouldResetStateFromServer: Bool = false - private var missingPeerIds = Set() + private var missingSsrcs = Set() private let updateDefaultMuteDisposable = MetaDisposable() @@ -811,8 +811,6 @@ public final class GroupCallParticipantsContext { }) strongSelf.activeSpeakersValue = peerIds - strongSelf.ensureHaveParticipants(peerIds: peerIds) - if !strongSelf.hasReceivedSpeakingParticipantsReport { var updatedParticipants = strongSelf.stateValue.state.participants var indexMap: [PeerId: Int] = [:] @@ -890,7 +888,7 @@ public final class GroupCallParticipantsContext { } } - public func reportSpeakingParticipants(ids: [PeerId]) { + public func reportSpeakingParticipants(ids: [PeerId: UInt32]) { if !ids.isEmpty { self.hasReceivedSpeakingParticipantsReport = true } @@ -906,7 +904,7 @@ public final class GroupCallParticipantsContext { let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 - for activityPeerId in ids { + for (activityPeerId, _) in ids { if let index = indexMap[activityPeerId] { var updateTimestamp = false if let activityTimestamp = updatedParticipants[index].activityTimestamp { @@ -947,30 +945,32 @@ public final class GroupCallParticipantsContext { overlayState: strongSelf.stateValue.overlayState ) } + + self.ensureHaveParticipants(ssrcs: Set(ids.map { $0.1 })) } - private func ensureHaveParticipants(peerIds: Set) { - var missingPeerIds = Set() + private func ensureHaveParticipants(ssrcs: Set) { + var missingSsrcs = Set() - var existingParticipantIds = Set() + var existingSsrcs = Set() for participant in self.stateValue.state.participants { - existingParticipantIds.insert(participant.peer.id) + existingSsrcs.insert(participant.ssrc) } - for peerId in peerIds { - if !existingParticipantIds.contains(peerId) { - missingPeerIds.insert(peerId) + for ssrc in ssrcs { + if !existingSsrcs.contains(ssrc) { + missingSsrcs.insert(ssrc) } } - if !missingPeerIds.isEmpty { - self.missingPeerIds.formUnion(missingPeerIds) - self.loadMissingPeers() + if !missingSsrcs.isEmpty { + self.missingSsrcs.formUnion(missingSsrcs) + self.loadMissingSsrcs() } } - private func loadMissingPeers() { - if self.missingPeerIds.isEmpty { + private func loadMissingSsrcs() { + if self.missingSsrcs.isEmpty { return } if self.isLoadingMore { @@ -978,16 +978,16 @@ public final class GroupCallParticipantsContext { } self.isLoadingMore = true - let peerIds = self.missingPeerIds + let ssrcs = self.missingSsrcs - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", peerIds: Array(peerIds), limit: 100) + self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: Array(ssrcs), limit: 100) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return } strongSelf.isLoadingMore = false - strongSelf.missingPeerIds.subtract(peerIds) + strongSelf.missingSsrcs.subtract(ssrcs) var updatedState = strongSelf.stateValue.state @@ -1013,7 +1013,7 @@ public final class GroupCallParticipantsContext { if strongSelf.shouldResetStateFromServer { strongSelf.resetStateFromServer() } else { - strongSelf.loadMissingPeers() + strongSelf.loadMissingSsrcs() } })) } @@ -1165,7 +1165,7 @@ public final class GroupCallParticipantsContext { self.updateQueue.removeAll() - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", peerIds: [], limit: 100) + self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: "", ssrcs: [], limit: 100) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return @@ -1285,7 +1285,7 @@ public final class GroupCallParticipantsContext { } self.isLoadingMore = true - self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, peerIds: [], limit: 100) + self.disposable.set((getGroupCallParticipants(account: self.account, callId: self.id, accessHash: self.accessHash, offset: token, ssrcs: [], limit: 100) |> deliverOnMainQueue).start(next: { [weak self] state in guard let strongSelf = self else { return