Broadcast fixes

This commit is contained in:
Ali 2021-03-09 20:02:56 +04:00
parent bc472b2126
commit 131ca67aff
11 changed files with 108 additions and 73 deletions

View File

@ -61,8 +61,6 @@ final class FFMpegAudioFrameDecoder: MediaTrackFrameDecoder {
}
return self.delayedFrames.remove(at: minFrameIndex)
}
} else {
assert(true)
}
return nil

View File

@ -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()
buffer.appendInt32(909354416)
buffer.appendInt32(-1322057861)
serializeInt32(flags, buffer: buffer, boxed: false)
call.serialize(buffer, true)
joinAs.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeString(inviteHash!, buffer: buffer, boxed: false)}
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)
var result: Api.Updates?
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()
buffer.appendInt32(2067345760)
buffer.appendInt32(-919505530)
serializeInt32(flags, buffer: buffer, boxed: false)
call.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
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)
var result: Api.Updates?
if let signature = reader.readInt32() {

View File

@ -842,14 +842,7 @@ public final class ManagedAudioSession {
private func updateOutputMode(_ outputMode: AudioSessionOutputMode) {
if let (type, currentOutputMode) = self.currentTypeAndOutputMode, currentOutputMode != outputMode {
//self.currentTypeAndOutputMode = (type, outputMode)
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)")
}
self.setup(type: type, outputMode: outputMode, activateNow: true)
}
}

View File

@ -352,6 +352,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private var internalState: InternalState = .requesting
private var callContext: OngoingGroupCallContext?
private var currentConnectionMode: OngoingGroupCallContext.ConnectionMode = .none
private var ssrcMapping: [UInt32: PeerId] = [:]
private var requestedSsrcs = Set<UInt32>()
@ -426,6 +427,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
public var canBeRemoved: Signal<Bool, NoError> {
return self._canBeRemoved.get()
}
private var markedAsCanBeRemoved = false
private let wasRemoved = Promise<Bool>(false)
@ -479,6 +481,15 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private let isMutedDisposable = MetaDisposable()
private let memberStatesDisposable = 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 isCurrentlyConnecting: Bool?
@ -652,13 +663,13 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
if participantUpdate.peerId == strongSelf.joinAsPeerId {
if case let .established(_, _, _, ssrc, _) = strongSelf.internalState, ssrc == participantUpdate.ssrc {
strongSelf._canBeRemoved.set(.single(true))
strongSelf.markAsCanBeRemoved()
}
}
} else if participantUpdate.peerId == strongSelf.joinAsPeerId {
if case let .established(_, connectionMode, _, ssrc, _) = strongSelf.internalState {
if ssrc != participantUpdate.ssrc {
strongSelf._canBeRemoved.set(.single(true))
strongSelf.markAsCanBeRemoved()
} else if case .broadcast = connectionMode {
let canUnmute: Bool
if let muteState = participantUpdate.muteState {
@ -668,7 +679,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
if canUnmute {
strongSelf.requestCall()
strongSelf.requestCall(movingFromBroadcastToRtc: true)
}
}
}
@ -682,7 +693,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
case let .call(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 {
@ -922,7 +933,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return
}
if case .established = strongSelf.internalState {
strongSelf.requestCall()
strongSelf.requestCall(movingFromBroadcastToRtc: false)
}
}
})
@ -981,10 +992,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
switch joinCallResult.connectionMode {
case .rtc:
strongSelf.callContext?.setConnectionMode(.rtc)
strongSelf.currentConnectionMode = .rtc
strongSelf.callContext?.setConnectionMode(.rtc, keepBroadcastConnectedIfWasEnabled: false)
strongSelf.callContext?.setJoinResponse(payload: clientParams, participants: addedParticipants)
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)
@ -1004,7 +1017,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
]), on: .root, blockInteraction: false, completion: {})
}
strongSelf._canBeRemoved.set(.single(true))
strongSelf.markAsCanBeRemoved()
}))
}))
@ -1014,12 +1027,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return
}
let mappedState: PresentationGroupCallState.NetworkState
switch state {
case .connecting:
mappedState = .connecting
case .connected:
if state.isConnected {
mappedState = .connected
} else {
mappedState = .connecting
}
let wasConnecting = strongSelf.stateValue.networkState == .connecting
if strongSelf.stateValue.networkState != mappedState {
strongSelf.stateValue.networkState = mappedState
@ -1035,8 +1048,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.checkCallDisposable = nil
}
}
strongSelf.isReconnectingAsSpeaker = state.isTransitioningFromBroadcastToRtc
if (wasConnecting != isConnecting && strongSelf.didConnectOnce) { //|| !strongSelf.didStartConnectingOnce {
if (wasConnecting != isConnecting && strongSelf.didConnectOnce) {
if isConnecting {
let toneRenderer = PresentationCallToneRenderer(tone: .groupConnecting)
strongSelf.toneRenderer = toneRenderer
@ -1050,7 +1065,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.didStartConnectingOnce = true
}
if case .connected = state {
if state.isConnected {
if !strongSelf.didConnectOnce {
strongSelf.didConnectOnce = true
@ -1176,8 +1191,9 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
participantsContext.activeSpeakers,
self.speakingParticipantsContext.get(),
adminIds,
myPeer
).start(next: { [weak self] state, activeSpeakers, speakingParticipants, adminIds, myPeer in
myPeer,
self.isReconnectingAsSpeakerPromise.get()
).start(next: { [weak self] state, activeSpeakers, speakingParticipants, adminIds, myPeer, isReconnectingAsSpeaker in
guard let strongSelf = self else {
return
}
@ -1246,7 +1262,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
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 {
switch strongSelf.isMutedValue {
case let .muted(isPushToTalkActive):
@ -1428,7 +1449,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return
}
strongSelf.checkCallDisposable = nil
strongSelf.requestCall()
strongSelf.requestCall(movingFromBroadcastToRtc: false)
})
}
}
@ -1441,6 +1462,11 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
private func markAsCanBeRemoved() {
if self.markedAsCanBeRemoved {
return
}
self.markedAsCanBeRemoved = true
self.callContext?.stop()
self._canBeRemoved.set(.single(true))
@ -1490,7 +1516,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
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)
}
private func requestCall() {
self.callContext?.setConnectionMode(.none)
private func requestCall(movingFromBroadcastToRtc: Bool) {
self.currentConnectionMode = .none
self.callContext?.setConnectionMode(.none, keepBroadcastConnectedIfWasEnabled: movingFromBroadcastToRtc)
self.missingSsrcsDisposable.set(nil)
self.missingSsrcs.removeAll()
@ -1783,8 +1810,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.checkCallDisposable?.dispose()
self.checkCallDisposable = nil
self.stateValue.networkState = .connecting
if !movingFromBroadcastToRtc {
self.stateValue.networkState = .connecting
}
self.requestDisposable.set((currentOrRequestedCall
|> deliverOnMainQueue).start(next: { [weak self] value in
@ -1797,7 +1826,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.updateSessionState(internalState: .active(value), audioSessionControl: strongSelf.audioSessionControl)
} else {
strongSelf._canBeRemoved.set(.single(true))
strongSelf.markAsCanBeRemoved()
}
}))
}

View File

@ -2742,7 +2742,7 @@ public final class VoiceChatController: ViewController {
let memberState: PeerEntry.State
var memberMuteState: GroupCallParticipantsContext.Participant.MuteState?
if member.raiseHandRating != nil {
if member.raiseHandRating != nil || member.hasRaiseHand {
memberState = .raisedHand
memberMuteState = member.muteState
} else if member.peer.id == self.callState?.myPeerId {

View File

@ -143,6 +143,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
jsonParams: jsonParams,
joinTimestamp: date,
raiseHandRating: raiseHandRating,
hasRaiseHand: raiseHandRating != nil,
activityTimestamp: activeDate.flatMap(Double.init),
activityRank: nil,
muteState: muteState,
@ -310,6 +311,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
jsonParams: jsonParams,
joinTimestamp: date,
raiseHandRating: raiseHandRating,
hasRaiseHand: raiseHandRating != nil,
activityTimestamp: activeDate.flatMap(Double.init),
activityRank: nil,
muteState: muteState,
@ -374,7 +376,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
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
if error.errorDescription == "GROUPCALL_ANONYMOUS_FORBIDDEN" {
return .anonymousNotAllowed
@ -689,6 +691,7 @@ public final class GroupCallParticipantsContext {
public var jsonParams: String?
public var joinTimestamp: Int32
public var raiseHandRating: Int64?
public var hasRaiseHand: Bool
public var activityTimestamp: Double?
public var activityRank: Int?
public var muteState: MuteState?
@ -701,6 +704,7 @@ public final class GroupCallParticipantsContext {
jsonParams: String?,
joinTimestamp: Int32,
raiseHandRating: Int64?,
hasRaiseHand: Bool,
activityTimestamp: Double?,
activityRank: Int?,
muteState: MuteState?,
@ -712,6 +716,7 @@ public final class GroupCallParticipantsContext {
self.jsonParams = jsonParams
self.joinTimestamp = joinTimestamp
self.raiseHandRating = raiseHandRating
self.hasRaiseHand = hasRaiseHand
self.activityTimestamp = activityTimestamp
self.activityRank = activityRank
self.muteState = muteState
@ -737,6 +742,9 @@ public final class GroupCallParticipantsContext {
if lhs.raiseHandRating != rhs.raiseHandRating {
return false
}
if lhs.hasRaiseHand != rhs.hasRaiseHand {
return false
}
if lhs.activityTimestamp != rhs.activityTimestamp {
return false
}
@ -948,17 +956,27 @@ public final class GroupCallParticipantsContext {
public var immediateState: State?
public var state: Signal<State, NoError> {
let accountPeerId = self.account.peerId
return self.statePromise.get()
|> map { state -> State in
if state.overlayState.isEmpty {
return 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 {
if let pendingMuteState = state.overlayState.pendingMuteStateChanges[publicState.participants[i].peer.id] {
publicState.participants[i].muteState = pendingMuteState.state
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
}
@ -1364,6 +1382,7 @@ public final class GroupCallParticipantsContext {
jsonParams: participantUpdate.jsonParams,
joinTimestamp: participantUpdate.joinTimestamp,
raiseHandRating: participantUpdate.raiseHandRating,
hasRaiseHand: participantUpdate.raiseHandRating != nil,
activityTimestamp: activityTimestamp,
activityRank: previousActivityRank,
muteState: participantUpdate.muteState,
@ -1749,7 +1768,7 @@ public func inviteToGroupCall(account: Account, callId: Int64, accessHash: Int64
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
return .generic
}

View File

@ -134,9 +134,9 @@ public final class OngoingGroupCallContext {
case broadcast
}
public enum NetworkState {
case connecting
case connected
public struct NetworkState: Equatable {
public var isConnected: Bool
public var isTransitioningFromBroadcastToRtc: Bool
}
public enum AudioLevelKey: Hashable {
@ -151,7 +151,7 @@ public final class OngoingGroupCallContext {
let sessionId = UInt32.random(in: 0 ..< UInt32(Int32.max))
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 audioLevels = ValuePipe<[(AudioLevelKey, Float, Bool)]>()
@ -210,16 +210,7 @@ public final class OngoingGroupCallContext {
guard let strongSelf = self else {
return
}
let mappedState: NetworkState
switch state {
case .connecting:
mappedState = .connecting
case .connected:
mappedState = .connected
@unknown default:
mappedState = .connecting
}
strongSelf.networkState.set(mappedState)
strongSelf.networkState.set(NetworkState(isConnected: state.isConnected, isTransitioningFromBroadcastToRtc: state.isTransitioningFromBroadcastToRtc))
}
}
@ -295,7 +286,7 @@ public final class OngoingGroupCallContext {
self.context.stop()
}
func setConnectionMode(_ connectionMode: ConnectionMode) {
func setConnectionMode(_ connectionMode: ConnectionMode, keepBroadcastConnectedIfWasEnabled: Bool) {
let mappedConnectionMode: OngoingCallConnectionMode
switch connectionMode {
case .none:
@ -305,7 +296,7 @@ public final class OngoingGroupCallContext {
case .broadcast:
mappedConnectionMode = .broadcast
}
self.context.setConnectionMode(mappedConnectionMode)
self.context.setConnectionMode(mappedConnectionMode, keepBroadcastConnectedIfWasEnabled: keepBroadcastConnectedIfWasEnabled)
if (mappedConnectionMode != .rtc) {
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
impl.setConnectionMode(connectionMode)
impl.setConnectionMode(connectionMode, keepBroadcastConnectedIfWasEnabled: keepBroadcastConnectedIfWasEnabled)
}
}

View File

@ -151,10 +151,10 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
- (void)switchAudioInput:(NSString * _Nonnull)deviceId;
@end
typedef NS_ENUM(int32_t, GroupCallNetworkState) {
GroupCallNetworkStateConnecting,
GroupCallNetworkStateConnected
};
typedef struct {
bool isConnected;
bool isTransitioningFromBroadcastToRtc;
} GroupCallNetworkState;
@interface OngoingGroupCallParticipantDescription : NSObject
@ -200,7 +200,7 @@ typedef NS_ENUM(int32_t, OngoingGroupCallBroadcastPartStatus) {
- (void)stop;
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode;
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled;
- (void)emitJoinPayload:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion;
- (void)setJoinResponsePayload:(NSString * _Nonnull)payload participants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants;

View File

@ -863,13 +863,16 @@ private:
__weak GroupCallThreadLocalContext *weakSelf = self;
_instance.reset(new tgcalls::GroupInstanceCustomImpl((tgcalls::GroupInstanceDescriptor){
.networkStateUpdated = [weakSelf, queue, networkStateUpdated](bool isConnected) {
.networkStateUpdated = [weakSelf, queue, networkStateUpdated](tgcalls::GroupNetworkState networkState) {
[queue dispatch:^{
__strong GroupCallThreadLocalContext *strongSelf = weakSelf;
if (strongSelf == nil) {
return;
}
networkStateUpdated(isConnected ? GroupCallNetworkStateConnected : GroupCallNetworkStateConnecting);
GroupCallNetworkState mappedState;
mappedState.isConnected = networkState.isConnected;
mappedState.isTransitioningFromBroadcastToRtc = networkState.isTransitioningFromBroadcastToRtc;
networkStateUpdated(mappedState);
}];
},
.audioLevelsUpdated = [audioLevelsUpdated](tgcalls::GroupLevelsUpdate const &levels) {
@ -1041,7 +1044,7 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
completion(string, payload.ssrc);
}
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode {
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled {
if (_instance) {
tgcalls::GroupConnectionMode mappedConnectionMode;
switch (connectionMode) {
@ -1062,7 +1065,7 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
break;
}
}
_instance->setConnectionMode(mappedConnectionMode);
_instance->setConnectionMode(mappedConnectionMode, keepBroadcastConnectedIfWasEnabled);
}
}

@ -1 +1 @@
Subproject commit 18ed939bf6818139f7147cde1c34cf22eb5080a2
Subproject commit d19c74b1474e4aab01d797373f1d62e4da5f87a5

View File

@ -1,5 +1,5 @@
{
"app": "7.5.1",
"app": "7.6",
"bazel": "4.0.0",
"xcode": "12.4"
}