mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-20 05:09:23 +00:00
Broadcast fixes
This commit is contained in:
parent
bc472b2126
commit
131ca67aff
@ -61,8 +61,6 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
|
|||||||
}
|
}
|
||||||
return self.delayedFrames.remove(at: minFrameIndex)
|
return self.delayedFrames.remove(at: minFrameIndex)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
assert(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -7670,14 +7670,15 @@ public extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
public static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer, inviteHash: String?, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(909354416)
|
buffer.appendInt32(-1322057861)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
call.serialize(buffer, true)
|
call.serialize(buffer, true)
|
||||||
joinAs.serialize(buffer, true)
|
joinAs.serialize(buffer, true)
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {serializeString(inviteHash!, buffer: buffer, boxed: false)}
|
||||||
params.serialize(buffer, true)
|
params.serialize(buffer, true)
|
||||||
return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", flags), ("call", call), ("joinAs", joinAs), ("params", params)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", flags), ("call", call), ("joinAs", joinAs), ("inviteHash", inviteHash), ("params", params)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
@ -7702,16 +7703,17 @@ public extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func inviteToGroupCall(call: Api.InputGroupCall, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
public static func inviteToGroupCall(flags: Int32, call: Api.InputGroupCall, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(2067345760)
|
buffer.appendInt32(-919505530)
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
call.serialize(buffer, true)
|
call.serialize(buffer, true)
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
buffer.appendInt32(Int32(users.count))
|
buffer.appendInt32(Int32(users.count))
|
||||||
for item in users {
|
for item in users {
|
||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}
|
}
|
||||||
return (FunctionDescription(name: "phone.inviteToGroupCall", parameters: [("call", call), ("users", users)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
return (FunctionDescription(name: "phone.inviteToGroupCall", parameters: [("flags", flags), ("call", call), ("users", users)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
|||||||
@ -842,14 +842,7 @@ public final class ManagedAudioSession {
|
|||||||
|
|
||||||
private func updateOutputMode(_ outputMode: AudioSessionOutputMode) {
|
private func updateOutputMode(_ outputMode: AudioSessionOutputMode) {
|
||||||
if let (type, currentOutputMode) = self.currentTypeAndOutputMode, currentOutputMode != outputMode {
|
if let (type, currentOutputMode) = self.currentTypeAndOutputMode, currentOutputMode != outputMode {
|
||||||
//self.currentTypeAndOutputMode = (type, outputMode)
|
self.setup(type: type, outputMode: outputMode, activateNow: true)
|
||||||
do {
|
|
||||||
try self.setup(type: type, outputMode: outputMode, activateNow: true)
|
|
||||||
//try self.setupOutputMode(outputMode, type: type)
|
|
||||||
//try self.activate()
|
|
||||||
} catch let error {
|
|
||||||
print("ManagedAudioSession overrideOutputAudioPort error \(error)")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -352,6 +352,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
private var internalState: InternalState = .requesting
|
private var internalState: InternalState = .requesting
|
||||||
|
|
||||||
private var callContext: OngoingGroupCallContext?
|
private var callContext: OngoingGroupCallContext?
|
||||||
|
private var currentConnectionMode: OngoingGroupCallContext.ConnectionMode = .none
|
||||||
private var ssrcMapping: [UInt32: PeerId] = [:]
|
private var ssrcMapping: [UInt32: PeerId] = [:]
|
||||||
|
|
||||||
private var requestedSsrcs = Set<UInt32>()
|
private var requestedSsrcs = Set<UInt32>()
|
||||||
@ -426,6 +427,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
public var canBeRemoved: Signal<Bool, NoError> {
|
public var canBeRemoved: Signal<Bool, NoError> {
|
||||||
return self._canBeRemoved.get()
|
return self._canBeRemoved.get()
|
||||||
}
|
}
|
||||||
|
private var markedAsCanBeRemoved = false
|
||||||
|
|
||||||
private let wasRemoved = Promise<Bool>(false)
|
private let wasRemoved = Promise<Bool>(false)
|
||||||
|
|
||||||
@ -479,6 +481,15 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
private let isMutedDisposable = MetaDisposable()
|
private let isMutedDisposable = MetaDisposable()
|
||||||
private let memberStatesDisposable = MetaDisposable()
|
private let memberStatesDisposable = MetaDisposable()
|
||||||
private let leaveDisposable = MetaDisposable()
|
private let leaveDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
private var isReconnectingAsSpeaker = false {
|
||||||
|
didSet {
|
||||||
|
if self.isReconnectingAsSpeaker != oldValue {
|
||||||
|
self.isReconnectingAsSpeakerPromise.set(self.isReconnectingAsSpeaker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private let isReconnectingAsSpeakerPromise = ValuePromise<Bool>(false)
|
||||||
|
|
||||||
private var checkCallDisposable: Disposable?
|
private var checkCallDisposable: Disposable?
|
||||||
private var isCurrentlyConnecting: Bool?
|
private var isCurrentlyConnecting: Bool?
|
||||||
@ -652,13 +663,13 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
if participantUpdate.peerId == strongSelf.joinAsPeerId {
|
if participantUpdate.peerId == strongSelf.joinAsPeerId {
|
||||||
if case let .established(_, _, _, ssrc, _) = strongSelf.internalState, ssrc == participantUpdate.ssrc {
|
if case let .established(_, _, _, ssrc, _) = strongSelf.internalState, ssrc == participantUpdate.ssrc {
|
||||||
strongSelf._canBeRemoved.set(.single(true))
|
strongSelf.markAsCanBeRemoved()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if participantUpdate.peerId == strongSelf.joinAsPeerId {
|
} else if participantUpdate.peerId == strongSelf.joinAsPeerId {
|
||||||
if case let .established(_, connectionMode, _, ssrc, _) = strongSelf.internalState {
|
if case let .established(_, connectionMode, _, ssrc, _) = strongSelf.internalState {
|
||||||
if ssrc != participantUpdate.ssrc {
|
if ssrc != participantUpdate.ssrc {
|
||||||
strongSelf._canBeRemoved.set(.single(true))
|
strongSelf.markAsCanBeRemoved()
|
||||||
} else if case .broadcast = connectionMode {
|
} else if case .broadcast = connectionMode {
|
||||||
let canUnmute: Bool
|
let canUnmute: Bool
|
||||||
if let muteState = participantUpdate.muteState {
|
if let muteState = participantUpdate.muteState {
|
||||||
@ -668,7 +679,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if canUnmute {
|
if canUnmute {
|
||||||
strongSelf.requestCall()
|
strongSelf.requestCall(movingFromBroadcastToRtc: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -682,7 +693,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
case let .call(isTerminated, _, _, _):
|
case let .call(isTerminated, _, _, _):
|
||||||
if isTerminated {
|
if isTerminated {
|
||||||
strongSelf._canBeRemoved.set(.single(true))
|
strongSelf.markAsCanBeRemoved()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -732,7 +743,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
self.requestCall()
|
self.requestCall(movingFromBroadcastToRtc: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -922,7 +933,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if case .established = strongSelf.internalState {
|
if case .established = strongSelf.internalState {
|
||||||
strongSelf.requestCall()
|
strongSelf.requestCall(movingFromBroadcastToRtc: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -981,10 +992,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
switch joinCallResult.connectionMode {
|
switch joinCallResult.connectionMode {
|
||||||
case .rtc:
|
case .rtc:
|
||||||
strongSelf.callContext?.setConnectionMode(.rtc)
|
strongSelf.currentConnectionMode = .rtc
|
||||||
|
strongSelf.callContext?.setConnectionMode(.rtc, keepBroadcastConnectedIfWasEnabled: false)
|
||||||
strongSelf.callContext?.setJoinResponse(payload: clientParams, participants: addedParticipants)
|
strongSelf.callContext?.setJoinResponse(payload: clientParams, participants: addedParticipants)
|
||||||
case .broadcast:
|
case .broadcast:
|
||||||
strongSelf.callContext?.setConnectionMode(.broadcast)
|
strongSelf.currentConnectionMode = .broadcast
|
||||||
|
strongSelf.callContext?.setConnectionMode(.broadcast, keepBroadcastConnectedIfWasEnabled: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.updateSessionState(internalState: .established(info: joinCallResult.callInfo, connectionMode: joinCallResult.connectionMode, clientParams: clientParams, localSsrc: ssrc, initialState: joinCallResult.state), audioSessionControl: strongSelf.audioSessionControl)
|
strongSelf.updateSessionState(internalState: .established(info: joinCallResult.callInfo, connectionMode: joinCallResult.connectionMode, clientParams: clientParams, localSsrc: ssrc, initialState: joinCallResult.state), audioSessionControl: strongSelf.audioSessionControl)
|
||||||
@ -1004,7 +1017,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
|
||||||
]), on: .root, blockInteraction: false, completion: {})
|
]), on: .root, blockInteraction: false, completion: {})
|
||||||
}
|
}
|
||||||
strongSelf._canBeRemoved.set(.single(true))
|
strongSelf.markAsCanBeRemoved()
|
||||||
}))
|
}))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -1014,12 +1027,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mappedState: PresentationGroupCallState.NetworkState
|
let mappedState: PresentationGroupCallState.NetworkState
|
||||||
switch state {
|
if state.isConnected {
|
||||||
case .connecting:
|
|
||||||
mappedState = .connecting
|
|
||||||
case .connected:
|
|
||||||
mappedState = .connected
|
mappedState = .connected
|
||||||
|
} else {
|
||||||
|
mappedState = .connecting
|
||||||
}
|
}
|
||||||
|
|
||||||
let wasConnecting = strongSelf.stateValue.networkState == .connecting
|
let wasConnecting = strongSelf.stateValue.networkState == .connecting
|
||||||
if strongSelf.stateValue.networkState != mappedState {
|
if strongSelf.stateValue.networkState != mappedState {
|
||||||
strongSelf.stateValue.networkState = mappedState
|
strongSelf.stateValue.networkState = mappedState
|
||||||
@ -1035,8 +1048,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
strongSelf.checkCallDisposable = nil
|
strongSelf.checkCallDisposable = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongSelf.isReconnectingAsSpeaker = state.isTransitioningFromBroadcastToRtc
|
||||||
|
|
||||||
if (wasConnecting != isConnecting && strongSelf.didConnectOnce) { //|| !strongSelf.didStartConnectingOnce {
|
if (wasConnecting != isConnecting && strongSelf.didConnectOnce) {
|
||||||
if isConnecting {
|
if isConnecting {
|
||||||
let toneRenderer = PresentationCallToneRenderer(tone: .groupConnecting)
|
let toneRenderer = PresentationCallToneRenderer(tone: .groupConnecting)
|
||||||
strongSelf.toneRenderer = toneRenderer
|
strongSelf.toneRenderer = toneRenderer
|
||||||
@ -1050,7 +1065,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
strongSelf.didStartConnectingOnce = true
|
strongSelf.didStartConnectingOnce = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .connected = state {
|
if state.isConnected {
|
||||||
if !strongSelf.didConnectOnce {
|
if !strongSelf.didConnectOnce {
|
||||||
strongSelf.didConnectOnce = true
|
strongSelf.didConnectOnce = true
|
||||||
|
|
||||||
@ -1176,8 +1191,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
participantsContext.activeSpeakers,
|
participantsContext.activeSpeakers,
|
||||||
self.speakingParticipantsContext.get(),
|
self.speakingParticipantsContext.get(),
|
||||||
adminIds,
|
adminIds,
|
||||||
myPeer
|
myPeer,
|
||||||
).start(next: { [weak self] state, activeSpeakers, speakingParticipants, adminIds, myPeer in
|
self.isReconnectingAsSpeakerPromise.get()
|
||||||
|
).start(next: { [weak self] state, activeSpeakers, speakingParticipants, adminIds, myPeer, isReconnectingAsSpeaker in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1246,7 +1262,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if participant.peer.id == strongSelf.joinAsPeerId {
|
if participant.peer.id == strongSelf.joinAsPeerId {
|
||||||
if let muteState = participant.muteState {
|
var filteredMuteState = participant.muteState
|
||||||
|
if isReconnectingAsSpeaker || strongSelf.currentConnectionMode != .rtc {
|
||||||
|
filteredMuteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let muteState = filteredMuteState {
|
||||||
if muteState.canUnmute {
|
if muteState.canUnmute {
|
||||||
switch strongSelf.isMutedValue {
|
switch strongSelf.isMutedValue {
|
||||||
case let .muted(isPushToTalkActive):
|
case let .muted(isPushToTalkActive):
|
||||||
@ -1428,7 +1449,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.checkCallDisposable = nil
|
strongSelf.checkCallDisposable = nil
|
||||||
strongSelf.requestCall()
|
strongSelf.requestCall(movingFromBroadcastToRtc: false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1441,6 +1462,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func markAsCanBeRemoved() {
|
private func markAsCanBeRemoved() {
|
||||||
|
if self.markedAsCanBeRemoved {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.markedAsCanBeRemoved = true
|
||||||
|
|
||||||
self.callContext?.stop()
|
self.callContext?.stop()
|
||||||
self._canBeRemoved.set(.single(true))
|
self._canBeRemoved.set(.single(true))
|
||||||
|
|
||||||
@ -1490,7 +1516,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
strongSelf.stateValue.myPeerId = peerId
|
strongSelf.stateValue.myPeerId = peerId
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.requestCall()
|
strongSelf.requestCall(movingFromBroadcastToRtc: false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1740,8 +1766,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
self.participantsContext?.updateShouldBeRecording(shouldBeRecording, title: title)
|
self.participantsContext?.updateShouldBeRecording(shouldBeRecording, title: title)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func requestCall() {
|
private func requestCall(movingFromBroadcastToRtc: Bool) {
|
||||||
self.callContext?.setConnectionMode(.none)
|
self.currentConnectionMode = .none
|
||||||
|
self.callContext?.setConnectionMode(.none, keepBroadcastConnectedIfWasEnabled: movingFromBroadcastToRtc)
|
||||||
|
|
||||||
self.missingSsrcsDisposable.set(nil)
|
self.missingSsrcsDisposable.set(nil)
|
||||||
self.missingSsrcs.removeAll()
|
self.missingSsrcs.removeAll()
|
||||||
@ -1783,8 +1810,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
self.checkCallDisposable?.dispose()
|
self.checkCallDisposable?.dispose()
|
||||||
self.checkCallDisposable = nil
|
self.checkCallDisposable = nil
|
||||||
|
|
||||||
self.stateValue.networkState = .connecting
|
if !movingFromBroadcastToRtc {
|
||||||
|
self.stateValue.networkState = .connecting
|
||||||
|
}
|
||||||
|
|
||||||
self.requestDisposable.set((currentOrRequestedCall
|
self.requestDisposable.set((currentOrRequestedCall
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||||
@ -1797,7 +1826,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||||||
|
|
||||||
strongSelf.updateSessionState(internalState: .active(value), audioSessionControl: strongSelf.audioSessionControl)
|
strongSelf.updateSessionState(internalState: .active(value), audioSessionControl: strongSelf.audioSessionControl)
|
||||||
} else {
|
} else {
|
||||||
strongSelf._canBeRemoved.set(.single(true))
|
strongSelf.markAsCanBeRemoved()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2742,7 +2742,7 @@ public final class VoiceChatController: ViewController {
|
|||||||
|
|
||||||
let memberState: PeerEntry.State
|
let memberState: PeerEntry.State
|
||||||
var memberMuteState: GroupCallParticipantsContext.Participant.MuteState?
|
var memberMuteState: GroupCallParticipantsContext.Participant.MuteState?
|
||||||
if member.raiseHandRating != nil {
|
if member.raiseHandRating != nil || member.hasRaiseHand {
|
||||||
memberState = .raisedHand
|
memberState = .raisedHand
|
||||||
memberMuteState = member.muteState
|
memberMuteState = member.muteState
|
||||||
} else if member.peer.id == self.callState?.myPeerId {
|
} else if member.peer.id == self.callState?.myPeerId {
|
||||||
|
|||||||
@ -143,6 +143,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
|||||||
jsonParams: jsonParams,
|
jsonParams: jsonParams,
|
||||||
joinTimestamp: date,
|
joinTimestamp: date,
|
||||||
raiseHandRating: raiseHandRating,
|
raiseHandRating: raiseHandRating,
|
||||||
|
hasRaiseHand: raiseHandRating != nil,
|
||||||
activityTimestamp: activeDate.flatMap(Double.init),
|
activityTimestamp: activeDate.flatMap(Double.init),
|
||||||
activityRank: nil,
|
activityRank: nil,
|
||||||
muteState: muteState,
|
muteState: muteState,
|
||||||
@ -310,6 +311,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
|||||||
jsonParams: jsonParams,
|
jsonParams: jsonParams,
|
||||||
joinTimestamp: date,
|
joinTimestamp: date,
|
||||||
raiseHandRating: raiseHandRating,
|
raiseHandRating: raiseHandRating,
|
||||||
|
hasRaiseHand: raiseHandRating != nil,
|
||||||
activityTimestamp: activeDate.flatMap(Double.init),
|
activityTimestamp: activeDate.flatMap(Double.init),
|
||||||
activityRank: nil,
|
activityRank: nil,
|
||||||
muteState: muteState,
|
muteState: muteState,
|
||||||
@ -374,7 +376,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
|
|||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return account.network.request(Api.functions.phone.joinGroupCall(flags: flags, call: .inputGroupCall(id: callId, accessHash: accessHash), joinAs: inputJoinAs, params: .dataJSON(data: joinPayload)))
|
return account.network.request(Api.functions.phone.joinGroupCall(flags: flags, call: .inputGroupCall(id: callId, accessHash: accessHash), joinAs: inputJoinAs, inviteHash: nil, params: .dataJSON(data: joinPayload)))
|
||||||
|> mapError { error -> JoinGroupCallError in
|
|> mapError { error -> JoinGroupCallError in
|
||||||
if error.errorDescription == "GROUPCALL_ANONYMOUS_FORBIDDEN" {
|
if error.errorDescription == "GROUPCALL_ANONYMOUS_FORBIDDEN" {
|
||||||
return .anonymousNotAllowed
|
return .anonymousNotAllowed
|
||||||
@ -689,6 +691,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
public var jsonParams: String?
|
public var jsonParams: String?
|
||||||
public var joinTimestamp: Int32
|
public var joinTimestamp: Int32
|
||||||
public var raiseHandRating: Int64?
|
public var raiseHandRating: Int64?
|
||||||
|
public var hasRaiseHand: Bool
|
||||||
public var activityTimestamp: Double?
|
public var activityTimestamp: Double?
|
||||||
public var activityRank: Int?
|
public var activityRank: Int?
|
||||||
public var muteState: MuteState?
|
public var muteState: MuteState?
|
||||||
@ -701,6 +704,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
jsonParams: String?,
|
jsonParams: String?,
|
||||||
joinTimestamp: Int32,
|
joinTimestamp: Int32,
|
||||||
raiseHandRating: Int64?,
|
raiseHandRating: Int64?,
|
||||||
|
hasRaiseHand: Bool,
|
||||||
activityTimestamp: Double?,
|
activityTimestamp: Double?,
|
||||||
activityRank: Int?,
|
activityRank: Int?,
|
||||||
muteState: MuteState?,
|
muteState: MuteState?,
|
||||||
@ -712,6 +716,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
self.jsonParams = jsonParams
|
self.jsonParams = jsonParams
|
||||||
self.joinTimestamp = joinTimestamp
|
self.joinTimestamp = joinTimestamp
|
||||||
self.raiseHandRating = raiseHandRating
|
self.raiseHandRating = raiseHandRating
|
||||||
|
self.hasRaiseHand = hasRaiseHand
|
||||||
self.activityTimestamp = activityTimestamp
|
self.activityTimestamp = activityTimestamp
|
||||||
self.activityRank = activityRank
|
self.activityRank = activityRank
|
||||||
self.muteState = muteState
|
self.muteState = muteState
|
||||||
@ -737,6 +742,9 @@ public final class GroupCallParticipantsContext {
|
|||||||
if lhs.raiseHandRating != rhs.raiseHandRating {
|
if lhs.raiseHandRating != rhs.raiseHandRating {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.hasRaiseHand != rhs.hasRaiseHand {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.activityTimestamp != rhs.activityTimestamp {
|
if lhs.activityTimestamp != rhs.activityTimestamp {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -948,17 +956,27 @@ public final class GroupCallParticipantsContext {
|
|||||||
public var immediateState: State?
|
public var immediateState: State?
|
||||||
|
|
||||||
public var state: Signal<State, NoError> {
|
public var state: Signal<State, NoError> {
|
||||||
|
let accountPeerId = self.account.peerId
|
||||||
return self.statePromise.get()
|
return self.statePromise.get()
|
||||||
|> map { state -> State in
|
|> map { state -> State in
|
||||||
if state.overlayState.isEmpty {
|
if state.overlayState.isEmpty {
|
||||||
return state.state
|
return state.state
|
||||||
}
|
}
|
||||||
var publicState = state.state
|
var publicState = state.state
|
||||||
|
var sortAgain = false
|
||||||
|
let canSeeHands = state.state.isCreator || state.state.adminIds.contains(accountPeerId)
|
||||||
for i in 0 ..< publicState.participants.count {
|
for i in 0 ..< publicState.participants.count {
|
||||||
if let pendingMuteState = state.overlayState.pendingMuteStateChanges[publicState.participants[i].peer.id] {
|
if let pendingMuteState = state.overlayState.pendingMuteStateChanges[publicState.participants[i].peer.id] {
|
||||||
publicState.participants[i].muteState = pendingMuteState.state
|
publicState.participants[i].muteState = pendingMuteState.state
|
||||||
publicState.participants[i].volume = pendingMuteState.volume
|
publicState.participants[i].volume = pendingMuteState.volume
|
||||||
}
|
}
|
||||||
|
if !canSeeHands && publicState.participants[i].raiseHandRating != nil {
|
||||||
|
publicState.participants[i].raiseHandRating = nil
|
||||||
|
sortAgain = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sortAgain {
|
||||||
|
publicState.participants.sort()
|
||||||
}
|
}
|
||||||
return publicState
|
return publicState
|
||||||
}
|
}
|
||||||
@ -1364,6 +1382,7 @@ public final class GroupCallParticipantsContext {
|
|||||||
jsonParams: participantUpdate.jsonParams,
|
jsonParams: participantUpdate.jsonParams,
|
||||||
joinTimestamp: participantUpdate.joinTimestamp,
|
joinTimestamp: participantUpdate.joinTimestamp,
|
||||||
raiseHandRating: participantUpdate.raiseHandRating,
|
raiseHandRating: participantUpdate.raiseHandRating,
|
||||||
|
hasRaiseHand: participantUpdate.raiseHandRating != nil,
|
||||||
activityTimestamp: activityTimestamp,
|
activityTimestamp: activityTimestamp,
|
||||||
activityRank: previousActivityRank,
|
activityRank: previousActivityRank,
|
||||||
muteState: participantUpdate.muteState,
|
muteState: participantUpdate.muteState,
|
||||||
@ -1749,7 +1768,7 @@ public func inviteToGroupCall(account: Account, callId: Int64, accessHash: Int64
|
|||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
return account.network.request(Api.functions.phone.inviteToGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), users: [apiUser]))
|
return account.network.request(Api.functions.phone.inviteToGroupCall(flags: 0, call: .inputGroupCall(id: callId, accessHash: accessHash), users: [apiUser]))
|
||||||
|> mapError { _ -> InviteToGroupCallError in
|
|> mapError { _ -> InviteToGroupCallError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|
|||||||
@ -134,9 +134,9 @@ public final class OngoingGroupCallContext {
|
|||||||
case broadcast
|
case broadcast
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum NetworkState {
|
public struct NetworkState: Equatable {
|
||||||
case connecting
|
public var isConnected: Bool
|
||||||
case connected
|
public var isTransitioningFromBroadcastToRtc: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AudioLevelKey: Hashable {
|
public enum AudioLevelKey: Hashable {
|
||||||
@ -151,7 +151,7 @@ public final class OngoingGroupCallContext {
|
|||||||
let sessionId = UInt32.random(in: 0 ..< UInt32(Int32.max))
|
let sessionId = UInt32.random(in: 0 ..< UInt32(Int32.max))
|
||||||
|
|
||||||
let joinPayload = Promise<(String, UInt32)>()
|
let joinPayload = Promise<(String, UInt32)>()
|
||||||
let networkState = ValuePromise<NetworkState>(.connecting, ignoreRepeated: true)
|
let networkState = ValuePromise<NetworkState>(NetworkState(isConnected: false, isTransitioningFromBroadcastToRtc: false), ignoreRepeated: true)
|
||||||
let isMuted = ValuePromise<Bool>(true, ignoreRepeated: true)
|
let isMuted = ValuePromise<Bool>(true, ignoreRepeated: true)
|
||||||
let audioLevels = ValuePipe<[(AudioLevelKey, Float, Bool)]>()
|
let audioLevels = ValuePipe<[(AudioLevelKey, Float, Bool)]>()
|
||||||
|
|
||||||
@ -210,16 +210,7 @@ public final class OngoingGroupCallContext {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let mappedState: NetworkState
|
strongSelf.networkState.set(NetworkState(isConnected: state.isConnected, isTransitioningFromBroadcastToRtc: state.isTransitioningFromBroadcastToRtc))
|
||||||
switch state {
|
|
||||||
case .connecting:
|
|
||||||
mappedState = .connecting
|
|
||||||
case .connected:
|
|
||||||
mappedState = .connected
|
|
||||||
@unknown default:
|
|
||||||
mappedState = .connecting
|
|
||||||
}
|
|
||||||
strongSelf.networkState.set(mappedState)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,7 +286,7 @@ public final class OngoingGroupCallContext {
|
|||||||
self.context.stop()
|
self.context.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setConnectionMode(_ connectionMode: ConnectionMode) {
|
func setConnectionMode(_ connectionMode: ConnectionMode, keepBroadcastConnectedIfWasEnabled: Bool) {
|
||||||
let mappedConnectionMode: OngoingCallConnectionMode
|
let mappedConnectionMode: OngoingCallConnectionMode
|
||||||
switch connectionMode {
|
switch connectionMode {
|
||||||
case .none:
|
case .none:
|
||||||
@ -305,7 +296,7 @@ public final class OngoingGroupCallContext {
|
|||||||
case .broadcast:
|
case .broadcast:
|
||||||
mappedConnectionMode = .broadcast
|
mappedConnectionMode = .broadcast
|
||||||
}
|
}
|
||||||
self.context.setConnectionMode(mappedConnectionMode)
|
self.context.setConnectionMode(mappedConnectionMode, keepBroadcastConnectedIfWasEnabled: keepBroadcastConnectedIfWasEnabled)
|
||||||
|
|
||||||
if (mappedConnectionMode != .rtc) {
|
if (mappedConnectionMode != .rtc) {
|
||||||
self.joinPayload.set(.never())
|
self.joinPayload.set(.never())
|
||||||
@ -504,9 +495,9 @@ public final class OngoingGroupCallContext {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setConnectionMode(_ connectionMode: ConnectionMode) {
|
public func setConnectionMode(_ connectionMode: ConnectionMode, keepBroadcastConnectedIfWasEnabled: Bool) {
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
impl.setConnectionMode(connectionMode)
|
impl.setConnectionMode(connectionMode, keepBroadcastConnectedIfWasEnabled: keepBroadcastConnectedIfWasEnabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -151,10 +151,10 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
|||||||
- (void)switchAudioInput:(NSString * _Nonnull)deviceId;
|
- (void)switchAudioInput:(NSString * _Nonnull)deviceId;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
typedef NS_ENUM(int32_t, GroupCallNetworkState) {
|
typedef struct {
|
||||||
GroupCallNetworkStateConnecting,
|
bool isConnected;
|
||||||
GroupCallNetworkStateConnected
|
bool isTransitioningFromBroadcastToRtc;
|
||||||
};
|
} GroupCallNetworkState;
|
||||||
|
|
||||||
@interface OngoingGroupCallParticipantDescription : NSObject
|
@interface OngoingGroupCallParticipantDescription : NSObject
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ typedef NS_ENUM(int32_t, OngoingGroupCallBroadcastPartStatus) {
|
|||||||
|
|
||||||
- (void)stop;
|
- (void)stop;
|
||||||
|
|
||||||
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode;
|
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled;
|
||||||
|
|
||||||
- (void)emitJoinPayload:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion;
|
- (void)emitJoinPayload:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion;
|
||||||
- (void)setJoinResponsePayload:(NSString * _Nonnull)payload participants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants;
|
- (void)setJoinResponsePayload:(NSString * _Nonnull)payload participants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants;
|
||||||
|
|||||||
@ -863,13 +863,16 @@ private:
|
|||||||
|
|
||||||
__weak GroupCallThreadLocalContext *weakSelf = self;
|
__weak GroupCallThreadLocalContext *weakSelf = self;
|
||||||
_instance.reset(new tgcalls::GroupInstanceCustomImpl((tgcalls::GroupInstanceDescriptor){
|
_instance.reset(new tgcalls::GroupInstanceCustomImpl((tgcalls::GroupInstanceDescriptor){
|
||||||
.networkStateUpdated = [weakSelf, queue, networkStateUpdated](bool isConnected) {
|
.networkStateUpdated = [weakSelf, queue, networkStateUpdated](tgcalls::GroupNetworkState networkState) {
|
||||||
[queue dispatch:^{
|
[queue dispatch:^{
|
||||||
__strong GroupCallThreadLocalContext *strongSelf = weakSelf;
|
__strong GroupCallThreadLocalContext *strongSelf = weakSelf;
|
||||||
if (strongSelf == nil) {
|
if (strongSelf == nil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
networkStateUpdated(isConnected ? GroupCallNetworkStateConnected : GroupCallNetworkStateConnecting);
|
GroupCallNetworkState mappedState;
|
||||||
|
mappedState.isConnected = networkState.isConnected;
|
||||||
|
mappedState.isTransitioningFromBroadcastToRtc = networkState.isTransitioningFromBroadcastToRtc;
|
||||||
|
networkStateUpdated(mappedState);
|
||||||
}];
|
}];
|
||||||
},
|
},
|
||||||
.audioLevelsUpdated = [audioLevelsUpdated](tgcalls::GroupLevelsUpdate const &levels) {
|
.audioLevelsUpdated = [audioLevelsUpdated](tgcalls::GroupLevelsUpdate const &levels) {
|
||||||
@ -1041,7 +1044,7 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
|
|||||||
completion(string, payload.ssrc);
|
completion(string, payload.ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode {
|
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled {
|
||||||
if (_instance) {
|
if (_instance) {
|
||||||
tgcalls::GroupConnectionMode mappedConnectionMode;
|
tgcalls::GroupConnectionMode mappedConnectionMode;
|
||||||
switch (connectionMode) {
|
switch (connectionMode) {
|
||||||
@ -1062,7 +1065,7 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_instance->setConnectionMode(mappedConnectionMode);
|
_instance->setConnectionMode(mappedConnectionMode, keepBroadcastConnectedIfWasEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 18ed939bf6818139f7147cde1c34cf22eb5080a2
|
Subproject commit d19c74b1474e4aab01d797373f1d62e4da5f87a5
|
||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "7.5.1",
|
"app": "7.6",
|
||||||
"bazel": "4.0.0",
|
"bazel": "4.0.0",
|
||||||
"xcode": "12.4"
|
"xcode": "12.4"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user