Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2021-03-24 02:09:47 +05:00
commit e2e63a4ddf
15 changed files with 184 additions and 125 deletions

View File

@ -283,6 +283,9 @@ public final class FFMpegMediaFrameSource: NSObject, MediaFrameSource {
let _ = currentSemaphore.swap(nil) let _ = currentSemaphore.swap(nil)
subscriber.putError(.generic) subscriber.putError(.generic)
} }
} else {
let _ = currentSemaphore.swap(nil)
subscriber.putError(.generic)
} }
} }
}) })

View File

@ -1,10 +1,30 @@
#if !os(macOS)
import UIKit import UIKit
#else
import AppKit
#endif
import CoreMedia import CoreMedia
import Accelerate import Accelerate
import FFMpegBinding import FFMpegBinding
private let bufferCount = 32 private let bufferCount = 32
#if os(macOS)
private let deviceColorSpace: CGColorSpace = {
if #available(OSX 10.11.2, *) {
if let colorSpace = CGColorSpace(name: CGColorSpace.displayP3) {
return colorSpace
} else {
return CGColorSpaceCreateDeviceRGB()
}
} else {
return CGColorSpaceCreateDeviceRGB()
}
}()
#else
private let deviceColorSpace: CGColorSpace = { private let deviceColorSpace: CGColorSpace = {
if #available(iOSApplicationExtension 9.3, iOS 9.3, *) { if #available(iOSApplicationExtension 9.3, iOS 9.3, *) {
if let colorSpace = CGColorSpace(name: CGColorSpace.displayP3) { if let colorSpace = CGColorSpace(name: CGColorSpace.displayP3) {
@ -16,7 +36,7 @@ private let deviceColorSpace: CGColorSpace = {
return CGColorSpaceCreateDeviceRGB() return CGColorSpaceCreateDeviceRGB()
} }
}() }()
#endif
public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder {
public enum ReceiveResult { public enum ReceiveResult {
case error case error

View File

@ -73,8 +73,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case optimizeDatabase(PresentationTheme) case optimizeDatabase(PresentationTheme)
case photoPreview(PresentationTheme, Bool) case photoPreview(PresentationTheme, Bool)
case knockoutWallpaper(PresentationTheme, Bool) case knockoutWallpaper(PresentationTheme, Bool)
case demoAudioStream(Bool) case demoVideoChats(Bool)
case snapPinListToTop(Bool)
case playerEmbedding(Bool) case playerEmbedding(Bool)
case playlistPlayback(Bool) case playlistPlayback(Bool)
case voiceConference case voiceConference
@ -94,7 +93,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.logging.rawValue return DebugControllerSection.logging.rawValue
case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .clearTips, .reimport, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .demoAudioStream, .snapPinListToTop, .playerEmbedding, .playlistPlayback, .voiceConference: case .clearTips, .reimport, .resetData, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .reindexUnread, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .demoVideoChats, .playerEmbedding, .playlistPlayback, .voiceConference:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .preferredVideoCodec: case .preferredVideoCodec:
return DebugControllerSection.videoExperiments.rawValue return DebugControllerSection.videoExperiments.rawValue
@ -155,10 +154,8 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 22 return 22
case .knockoutWallpaper: case .knockoutWallpaper:
return 23 return 23
case .demoAudioStream: case .demoVideoChats:
return 24 return 24
case .snapPinListToTop:
return 25
case .playerEmbedding: case .playerEmbedding:
return 26 return 26
case .playlistPlayback: case .playlistPlayback:
@ -706,22 +703,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
}) })
}).start() }).start()
}) })
case let .demoAudioStream(value): case let .demoVideoChats(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Demo Audio Stream", value: value, sectionId: self.section, style: .blocks, updated: { value in return ItemListSwitchItem(presentationData: presentationData, title: "Demo Video", value: value, sectionId: self.section, style: .blocks, updated: { value in
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
settings.demoAudioStream = value settings.demoVideoChats = value
return settings
})
}).start()
})
case let .snapPinListToTop(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Pin List Top Edge", value: value, sectionId: self.section, style: .blocks, updated: { value in
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
settings.snapPinListToTop = value
return settings return settings
}) })
}).start() }).start()
@ -824,10 +811,8 @@ private func debugControllerEntries(presentationData: PresentationData, loggingS
entries.append(.resetHoles(presentationData.theme)) entries.append(.resetHoles(presentationData.theme))
entries.append(.reindexUnread(presentationData.theme)) entries.append(.reindexUnread(presentationData.theme))
entries.append(.optimizeDatabase(presentationData.theme)) entries.append(.optimizeDatabase(presentationData.theme))
//entries.append(.photoPreview(presentationData.theme, experimentalSettings.chatListPhotos))
entries.append(.knockoutWallpaper(presentationData.theme, experimentalSettings.knockoutWallpaper)) entries.append(.knockoutWallpaper(presentationData.theme, experimentalSettings.knockoutWallpaper))
entries.append(.demoAudioStream(experimentalSettings.demoAudioStream)) entries.append(.demoVideoChats(experimentalSettings.demoVideoChats))
entries.append(.snapPinListToTop(experimentalSettings.snapPinListToTop))
entries.append(.playerEmbedding(experimentalSettings.playerEmbedding)) entries.append(.playerEmbedding(experimentalSettings.playerEmbedding))
entries.append(.playlistPlayback(experimentalSettings.playlistPlayback)) entries.append(.playlistPlayback(experimentalSettings.playlistPlayback))

View File

@ -142,7 +142,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[767652808] = { return Api.InputEncryptedFile.parse_inputEncryptedFileBigUploaded($0) } dict[767652808] = { return Api.InputEncryptedFile.parse_inputEncryptedFileBigUploaded($0) }
dict[1304052993] = { return Api.account.Takeout.parse_takeout($0) } dict[1304052993] = { return Api.account.Takeout.parse_takeout($0) }
dict[-1456996667] = { return Api.messages.InactiveChats.parse_inactiveChats($0) } dict[-1456996667] = { return Api.messages.InactiveChats.parse_inactiveChats($0) }
dict[430815881] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) } dict[-1184160274] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
dict[1443858741] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedMessage($0) } dict[1443858741] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedMessage($0) }
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) } dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) } dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }

View File

@ -3604,13 +3604,13 @@ public extension Api {
} }
public enum GroupCallParticipant: TypeConstructorDescription { public enum GroupCallParticipant: TypeConstructorDescription {
case groupCallParticipant(flags: Int32, peer: Api.Peer, date: Int32, activeDate: Int32?, source: Int32, volume: Int32?, about: String?, raiseHandRating: Int64?) case groupCallParticipant(flags: Int32, peer: Api.Peer, date: Int32, activeDate: Int32?, source: Int32, volume: Int32?, about: String?, raiseHandRating: Int64?, params: Api.DataJSON?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about, let raiseHandRating): case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about, let raiseHandRating, let params):
if boxed { if boxed {
buffer.appendInt32(430815881) buffer.appendInt32(-1184160274)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
@ -3620,14 +3620,15 @@ public extension Api {
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 7) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeString(about!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 11) != 0 {serializeString(about!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 13) != 0 {serializeInt64(raiseHandRating!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 13) != 0 {serializeInt64(raiseHandRating!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 6) != 0 {params!.serialize(buffer, true)}
break break
} }
} }
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about, let raiseHandRating): case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about, let raiseHandRating, let params):
return ("groupCallParticipant", [("flags", flags), ("peer", peer), ("date", date), ("activeDate", activeDate), ("source", source), ("volume", volume), ("about", about), ("raiseHandRating", raiseHandRating)]) return ("groupCallParticipant", [("flags", flags), ("peer", peer), ("date", date), ("activeDate", activeDate), ("source", source), ("volume", volume), ("about", about), ("raiseHandRating", raiseHandRating), ("params", params)])
} }
} }
@ -3650,6 +3651,10 @@ public extension Api {
if Int(_1!) & Int(1 << 11) != 0 {_7 = parseString(reader) } if Int(_1!) & Int(1 << 11) != 0 {_7 = parseString(reader) }
var _8: Int64? var _8: Int64?
if Int(_1!) & Int(1 << 13) != 0 {_8 = reader.readInt64() } if Int(_1!) & Int(1 << 13) != 0 {_8 = reader.readInt64() }
var _9: Api.DataJSON?
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.DataJSON
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
@ -3658,8 +3663,9 @@ public extension Api {
let _c6 = (Int(_1!) & Int(1 << 7) == 0) || _6 != nil let _c6 = (Int(_1!) & Int(1 << 7) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 11) == 0) || _7 != nil let _c7 = (Int(_1!) & Int(1 << 11) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 13) == 0) || _8 != nil let _c8 = (Int(_1!) & Int(1 << 13) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
return Api.GroupCallParticipant.groupCallParticipant(flags: _1!, peer: _2!, date: _3!, activeDate: _4, source: _5!, volume: _6, about: _7, raiseHandRating: _8) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.GroupCallParticipant.groupCallParticipant(flags: _1!, peer: _2!, date: _3!, activeDate: _4, source: _5!, volume: _6, about: _7, raiseHandRating: _8, params: _9)
} }
else { else {
return nil return nil

View File

@ -571,8 +571,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.statePromise = ValuePromise(self.stateValue) self.statePromise = ValuePromise(self.stateValue)
self.temporaryJoinTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) self.temporaryJoinTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
//self.videoCapturer = OngoingCallVideoCapturer(keepLandscape: true) if accountContext.sharedContext.immediateExperimentalUISettings.demoVideoChats {
self.videoCapturer = OngoingCallVideoCapturer(keepLandscape: false)
}
self.isVideo = self.videoCapturer != nil self.isVideo = self.videoCapturer != nil
var didReceiveAudioOutputs = false var didReceiveAudioOutputs = false
@ -1039,6 +1041,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
if let current = self.callContext { if let current = self.callContext {
callContext = current callContext = current
} else { } else {
var outgoingAudioBitrateKbit: Int32?
let appConfiguration = self.accountContext.currentAppConfiguration.with({ $0 })
if let data = appConfiguration.data, let value = data["voice_chat_send_bitrate"] as? Int32 {
outgoingAudioBitrateKbit = value
}
callContext = OngoingGroupCallContext(video: self.videoCapturer, participantDescriptionsRequired: { [weak self] ssrcs in callContext = OngoingGroupCallContext(video: self.videoCapturer, participantDescriptionsRequired: { [weak self] ssrcs in
Queue.mainQueue().async { Queue.mainQueue().async {
guard let strongSelf = self else { guard let strongSelf = self else {
@ -1055,7 +1063,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.requestCall(movingFromBroadcastToRtc: false) strongSelf.requestCall(movingFromBroadcastToRtc: false)
} }
} }
}) }, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit, enableVideo: self.isVideo)
self.incomingVideoSourcePromise.set(callContext.videoSources self.incomingVideoSourcePromise.set(callContext.videoSources
|> deliverOnMainQueue |> deliverOnMainQueue
|> map { [weak self] sources -> [PeerId: UInt32] in |> map { [weak self] sources -> [PeerId: UInt32] in

View File

@ -178,6 +178,8 @@ final class GroupVideoNode: ASDisplayNode {
self.videoViewContainer.addSubview(self.videoView.view) self.videoViewContainer.addSubview(self.videoView.view)
self.view.addSubview(self.videoViewContainer) self.view.addSubview(self.videoViewContainer)
self.clipsToBounds = true
videoView.setOnFirstFrameReceived({ [weak self] _ in videoView.setOnFirstFrameReceived({ [weak self] _ in
Queue.mainQueue().async { Queue.mainQueue().async {
guard let strongSelf = self else { guard let strongSelf = self else {
@ -270,6 +272,7 @@ private final class MainVideoContainerNode: ASDisplayNode {
private let call: PresentationGroupCall private let call: PresentationGroupCall
private var currentVideoNode: GroupVideoNode? private var currentVideoNode: GroupVideoNode?
private var candidateVideoNode: GroupVideoNode?
private var currentPeer: (PeerId, UInt32)? private var currentPeer: (PeerId, UInt32)?
private var validLayout: CGSize? private var validLayout: CGSize?
@ -283,7 +286,7 @@ private final class MainVideoContainerNode: ASDisplayNode {
self.backgroundColor = .black self.backgroundColor = .black
} }
func updatePeer(peer: (peerId: PeerId, source: UInt32)?) { func updatePeer(peer: (peerId: PeerId, source: UInt32)?, waitForFullSize: Bool) {
if self.currentPeer?.0 == peer?.0 && self.currentPeer?.1 == peer?.1 { if self.currentPeer?.0 == peer?.0 && self.currentPeer?.1 == peer?.1 {
return return
} }
@ -294,15 +297,40 @@ private final class MainVideoContainerNode: ASDisplayNode {
guard let strongSelf = self, let videoView = videoView else { guard let strongSelf = self, let videoView = videoView else {
return return
} }
let videoNode = GroupVideoNode(videoView: videoView)
if let currentVideoNode = strongSelf.currentVideoNode { if waitForFullSize {
currentVideoNode.removeFromSupernode() let candidateVideoNode = GroupVideoNode(videoView: videoView)
strongSelf.currentVideoNode = nil strongSelf.candidateVideoNode = candidateVideoNode
}
strongSelf.currentVideoNode = videoNode Queue.mainQueue().after(0.3, { [weak candidateVideoNode] in
strongSelf.addSubnode(videoNode) guard let strongSelf = self, let videoNode = candidateVideoNode, videoNode === strongSelf.candidateVideoNode else {
if let size = strongSelf.validLayout { return
strongSelf.update(size: size, transition: .immediate) }
if let currentVideoNode = strongSelf.currentVideoNode {
currentVideoNode.removeFromSupernode()
strongSelf.currentVideoNode = nil
}
strongSelf.currentVideoNode = videoNode
strongSelf.addSubnode(videoNode)
if let size = strongSelf.validLayout {
strongSelf.update(size: size, transition: .immediate)
}
})
} else {
strongSelf.candidateVideoNode = nil
let videoNode = GroupVideoNode(videoView: videoView)
if let currentVideoNode = strongSelf.currentVideoNode {
currentVideoNode.removeFromSupernode()
strongSelf.currentVideoNode = nil
}
strongSelf.currentVideoNode = videoNode
strongSelf.addSubnode(videoNode)
if let size = strongSelf.validLayout {
strongSelf.update(size: size, transition: .immediate)
}
} }
} }
}) })
@ -778,9 +806,9 @@ public final class VoiceChatController: ViewController {
self.backgroundNode.backgroundColor = secondaryPanelBackgroundColor self.backgroundNode.backgroundColor = secondaryPanelBackgroundColor
self.backgroundNode.clipsToBounds = false self.backgroundNode.clipsToBounds = false
/*if false { if sharedContext.immediateExperimentalUISettings.demoVideoChats {
self.mainVideoContainer = MainVideoContainerNode(context: call.accountContext, call: call) self.mainVideoContainer = MainVideoContainerNode(context: call.accountContext, call: call)
}*/ }
self.listNode = ListView() self.listNode = ListView()
self.listNode.verticalScrollIndicatorColor = UIColor(white: 1.0, alpha: 0.3) self.listNode.verticalScrollIndicatorColor = UIColor(white: 1.0, alpha: 0.3)
@ -874,12 +902,6 @@ public final class VoiceChatController: ViewController {
let _ = self?.call.updateMuteState(peerId: peerId, isMuted: isMuted) let _ = self?.call.updateMuteState(peerId: peerId, isMuted: isMuted)
}, openPeer: { [weak self] peerId in }, openPeer: { [weak self] peerId in
if let strongSelf = self { if let strongSelf = self {
/*let context = strongSelf.context
strongSelf.controller?.dismiss(completion: {
Queue.mainQueue().justDispatch {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), keepStack: .always, purposefulAction: {}, peekData: nil))
}
})*/
for entry in strongSelf.currentEntries { for entry in strongSelf.currentEntries {
switch entry { switch entry {
case let .peer(peer): case let .peer(peer):
@ -888,11 +910,11 @@ public final class VoiceChatController: ViewController {
if strongSelf.currentDominantSpeakerWithVideo?.0 != peerId || strongSelf.currentDominantSpeakerWithVideo?.1 != source { if strongSelf.currentDominantSpeakerWithVideo?.0 != peerId || strongSelf.currentDominantSpeakerWithVideo?.1 != source {
strongSelf.currentDominantSpeakerWithVideo = (peerId, source) strongSelf.currentDominantSpeakerWithVideo = (peerId, source)
strongSelf.call.setFullSizeVideo(peerId: peerId) strongSelf.call.setFullSizeVideo(peerId: peerId)
strongSelf.mainVideoContainer?.updatePeer(peer: (peerId: peerId, source: source)) strongSelf.mainVideoContainer?.updatePeer(peer: (peerId: peerId, source: source), waitForFullSize: false)
} else { } else {
strongSelf.currentDominantSpeakerWithVideo = nil strongSelf.currentDominantSpeakerWithVideo = nil
strongSelf.call.setFullSizeVideo(peerId: nil) strongSelf.call.setFullSizeVideo(peerId: nil)
strongSelf.mainVideoContainer?.updatePeer(peer: nil) strongSelf.mainVideoContainer?.updatePeer(peer: nil, waitForFullSize: false)
} }
} }
} }
@ -1182,17 +1204,19 @@ public final class VoiceChatController: ViewController {
} }
}), true)) }), true))
} }
/*items.append(.action(ContextMenuActionItem(text: "Toggle Full Screen", icon: { theme in if strongSelf.context.sharedContext.immediateExperimentalUISettings.demoVideoChats {
return nil items.append(.action(ContextMenuActionItem(text: "Toggle Full Screen", icon: { theme in
}, action: { _, f in return nil
guard let strongSelf = self else { }, action: { _, f in
return guard let strongSelf = self else {
} return
}
strongSelf.itemInteraction?.openPeer(peer.id)
f(.default) strongSelf.itemInteraction?.openPeer(peer.id)
})))*/ f(.default)
})))
}
if peer.id == strongSelf.callState?.myPeerId { if peer.id == strongSelf.callState?.myPeerId {
if entry.raisedHand { if entry.raisedHand {
@ -1598,7 +1622,7 @@ public final class VoiceChatController: ViewController {
if strongSelf.currentDominantSpeakerWithVideo?.0 != peerId || strongSelf.currentDominantSpeakerWithVideo?.1 != source { if strongSelf.currentDominantSpeakerWithVideo?.0 != peerId || strongSelf.currentDominantSpeakerWithVideo?.1 != source {
strongSelf.currentDominantSpeakerWithVideo = (peerId, source) strongSelf.currentDominantSpeakerWithVideo = (peerId, source)
strongSelf.call.setFullSizeVideo(peerId: peerId) strongSelf.call.setFullSizeVideo(peerId: peerId)
strongSelf.mainVideoContainer?.updatePeer(peer: (peerId: peerId, source: source)) strongSelf.mainVideoContainer?.updatePeer(peer: (peerId: peerId, source: source), waitForFullSize: true)
} }
} }
@ -1750,7 +1774,7 @@ public final class VoiceChatController: ViewController {
if !validSources.contains(source) { if !validSources.contains(source) {
strongSelf.currentDominantSpeakerWithVideo = nil strongSelf.currentDominantSpeakerWithVideo = nil
strongSelf.call.setFullSizeVideo(peerId: nil) strongSelf.call.setFullSizeVideo(peerId: nil)
strongSelf.mainVideoContainer?.updatePeer(peer: nil) strongSelf.mainVideoContainer?.updatePeer(peer: nil, waitForFullSize: false)
} }
} }
@ -2534,7 +2558,7 @@ public final class VoiceChatController: ViewController {
let topPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: panelOffset), size: CGSize(width: size.width, height: topPanelHeight)) let topPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: panelOffset), size: CGSize(width: size.width, height: topPanelHeight))
if let mainVideoContainer = self.mainVideoContainer { if let mainVideoContainer = self.mainVideoContainer {
let videoContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: layout.size.width, height: 200.0)) let videoContainerFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: layout.size.width, height: min(300.0, layout.size.width)))
transition.updateFrameAdditive(node: mainVideoContainer, frame: videoContainerFrame) transition.updateFrameAdditive(node: mainVideoContainer, frame: videoContainerFrame)
mainVideoContainer.update(size: videoContainerFrame.size, transition: transition) mainVideoContainer.update(size: videoContainerFrame.size, transition: transition)
} }
@ -2805,7 +2829,7 @@ public final class VoiceChatController: ViewController {
let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom
var listTopInset = layoutTopInset + topPanelHeight var listTopInset = layoutTopInset + topPanelHeight
if self.mainVideoContainer != nil { if self.mainVideoContainer != nil {
listTopInset += 200.0 listTopInset += min(300.0, layout.size.width)
} }
let listSize = CGSize(width: size.width, height: layout.size.height - listTopInset - bottomPanelHeight) let listSize = CGSize(width: size.width, height: layout.size.height - listTopInset - bottomPanelHeight)

View File

@ -110,7 +110,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
loop: for participant in participants { loop: for participant in participants {
switch participant { switch participant {
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, params):
let peerId: PeerId let peerId: PeerId
switch apiPeerId { switch apiPeerId {
case let .peerUser(userId): case let .peerUser(userId):
@ -134,13 +134,13 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
} else if mutedByYou { } else if mutedByYou {
muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: mutedByYou) muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: mutedByYou)
} }
let jsonParams: String? = nil var jsonParams: String? = nil
/*if let params = params { if let params = params {
switch params { switch params {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data jsonParams = data
} }
}*/ }
parsedParticipants.append(GroupCallParticipantsContext.Participant( parsedParticipants.append(GroupCallParticipantsContext.Participant(
peer: peer, peer: peer,
ssrc: ssrc, ssrc: ssrc,
@ -297,7 +297,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
loop: for participant in participants { loop: for participant in participants {
switch participant { switch participant {
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, params):
let peerId: PeerId let peerId: PeerId
switch apiPeerId { switch apiPeerId {
case let .peerUser(userId): case let .peerUser(userId):
@ -320,13 +320,13 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
} else if mutedByYou { } else if mutedByYou {
muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: mutedByYou) muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: mutedByYou)
} }
let jsonParams: String? = nil var jsonParams: String? = nil
/*if let params = params { if let params = params {
switch params { switch params {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data jsonParams = data
} }
}*/ }
parsedParticipants.append(GroupCallParticipantsContext.Participant( parsedParticipants.append(GroupCallParticipantsContext.Participant(
peer: peer, peer: peer,
ssrc: ssrc, ssrc: ssrc,
@ -525,7 +525,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
case let .updateGroupCallParticipants(_, participants, _): case let .updateGroupCallParticipants(_, participants, _):
loop: for participant in participants { loop: for participant in participants {
switch participant { switch participant {
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, params):
let peerId: PeerId let peerId: PeerId
switch apiPeerId { switch apiPeerId {
case let .peerUser(userId): case let .peerUser(userId):
@ -548,13 +548,13 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
} else if mutedByYou { } else if mutedByYou {
muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: mutedByYou) muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: false, mutedByYou: mutedByYou)
} }
let jsonParams: String? = nil var jsonParams: String? = nil
/*if let params = params { if let params = params {
switch params { switch params {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data jsonParams = data
} }
}*/ }
if !state.participants.contains(where: { $0.peer.id == peer.id }) { if !state.participants.contains(where: { $0.peer.id == peer.id }) {
state.participants.append(GroupCallParticipantsContext.Participant( state.participants.append(GroupCallParticipantsContext.Participant(
peer: peer, peer: peer,
@ -797,6 +797,12 @@ public final class GroupCallParticipantsContext {
} }
public static func compare(lhs: Participant, rhs: Participant, sortAscending: Bool) -> Bool { public static func compare(lhs: Participant, rhs: Participant, sortAscending: Bool) -> Bool {
let lhsCanUnmute = lhs.muteState?.canUnmute ?? true
let rhsCanUnmute = rhs.muteState?.canUnmute ?? true
if lhsCanUnmute != rhsCanUnmute {
return lhsCanUnmute
}
if let lhsActivityRank = lhs.activityRank, let rhsActivityRank = rhs.activityRank { if let lhsActivityRank = lhs.activityRank, let rhsActivityRank = rhs.activityRank {
if lhsActivityRank != rhsActivityRank { if lhsActivityRank != rhsActivityRank {
return lhsActivityRank < rhsActivityRank return lhsActivityRank < rhsActivityRank
@ -1440,6 +1446,11 @@ public final class GroupCallParticipantsContext {
activityTimestamp = participantUpdate.activityTimestamp ?? previousActivityTimestamp activityTimestamp = participantUpdate.activityTimestamp ?? previousActivityTimestamp
} }
if let muteState = participantUpdate.muteState, !muteState.canUnmute {
previousActivityRank = nil
activityTimestamp = nil
}
var volume = participantUpdate.volume var volume = participantUpdate.volume
var muteState = participantUpdate.muteState var muteState = participantUpdate.muteState
if participantUpdate.isMin { if participantUpdate.isMin {
@ -1720,7 +1731,7 @@ public final class GroupCallParticipantsContext {
extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate { extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
init(_ apiParticipant: Api.GroupCallParticipant) { init(_ apiParticipant: Api.GroupCallParticipant) {
switch apiParticipant { switch apiParticipant {
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, params):
let peerId: PeerId let peerId: PeerId
switch apiPeerId { switch apiPeerId {
case let .peerUser(userId): case let .peerUser(userId):
@ -1753,13 +1764,13 @@ extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
participationStatusChange = .none participationStatusChange = .none
} }
let jsonParams: String? = nil var jsonParams: String? = nil
/*if let params = params { if let params = params {
switch params { switch params {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data jsonParams = data
} }
}*/ }
self.init( self.init(
peerId: peerId, peerId: peerId,
@ -1783,7 +1794,7 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
var participantUpdates: [GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate] = [] var participantUpdates: [GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate] = []
for participant in participants { for participant in participants {
switch participant { switch participant {
case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, params):
let peerId: PeerId let peerId: PeerId
switch apiPeerId { switch apiPeerId {
case let .peerUser(userId): case let .peerUser(userId):
@ -1816,13 +1827,13 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
participationStatusChange = .none participationStatusChange = .none
} }
let jsonParams: String? = nil var jsonParams: String? = nil
/*if let params = params { if let params = params {
switch params { switch params {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data jsonParams = data
} }
}*/ }
participantUpdates.append(GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate( participantUpdates.append(GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(
peerId: peerId, peerId: peerId,

View File

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization { public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt { public func currentLayer() -> UInt {
return 126 return 127
} }
public func parseMessage(_ data: Data!) -> Any! { public func parseMessage(_ data: Data!) -> Any! {

View File

@ -3722,13 +3722,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var isScrolled: Bool var isScrolled: Bool
} }
let messageRangeEdge: Signal<Bool, NoError> = self.context.sharedContext.accountManager.sharedData(keys: Set([ApplicationSpecificSharedDataKeys.experimentalUISettings]))
|> map { sharedData -> Bool in
let experimentalSettings: ExperimentalUISettings = (sharedData.entries[ApplicationSpecificSharedDataKeys.experimentalUISettings] as? ExperimentalUISettings) ?? ExperimentalUISettings.defaultSettings
return experimentalSettings.snapPinListToTop
}
|> distinctUntilChanged
let referenceMessage: Signal<ReferenceMessage?, NoError> let referenceMessage: Signal<ReferenceMessage?, NoError>
if latest { if latest {
referenceMessage = .single(nil) referenceMessage = .single(nil)
@ -3736,16 +3729,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
referenceMessage = combineLatest( referenceMessage = combineLatest(
queue: Queue.mainQueue(), queue: Queue.mainQueue(),
self.scrolledToMessageId.get(), self.scrolledToMessageId.get(),
self.chatDisplayNode.historyNode.topVisibleMessageRange.get(), self.chatDisplayNode.historyNode.topVisibleMessageRange.get()
messageRangeEdge
) )
|> map { scrolledToMessageId, topVisibleMessageRange, messageRangeEdge -> ReferenceMessage? in |> map { scrolledToMessageId, topVisibleMessageRange -> ReferenceMessage? in
let topVisibleMessage: MessageId? let topVisibleMessage: MessageId?
if messageRangeEdge { topVisibleMessage = topVisibleMessageRange?.upperBound
topVisibleMessage = topVisibleMessageRange?.lowerBound
} else {
topVisibleMessage = topVisibleMessageRange?.upperBound
}
if let scrolledToMessageId = scrolledToMessageId { if let scrolledToMessageId = scrolledToMessageId {
if let topVisibleMessage = topVisibleMessage { if let topVisibleMessage = topVisibleMessage {

View File

@ -14,8 +14,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
public var preferredVideoCodec: String? public var preferredVideoCodec: String?
public var disableVideoAspectScaling: Bool public var disableVideoAspectScaling: Bool
public var enableVoipTcp: Bool public var enableVoipTcp: Bool
public var snapPinListToTop: Bool public var demoVideoChats: Bool
public var demoAudioStream: Bool
public static var defaultSettings: ExperimentalUISettings { public static var defaultSettings: ExperimentalUISettings {
return ExperimentalUISettings( return ExperimentalUISettings(
@ -30,8 +29,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
preferredVideoCodec: nil, preferredVideoCodec: nil,
disableVideoAspectScaling: false, disableVideoAspectScaling: false,
enableVoipTcp: false, enableVoipTcp: false,
snapPinListToTop: false, demoVideoChats: false
demoAudioStream: false
) )
} }
@ -47,8 +45,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
preferredVideoCodec: String?, preferredVideoCodec: String?,
disableVideoAspectScaling: Bool, disableVideoAspectScaling: Bool,
enableVoipTcp: Bool, enableVoipTcp: Bool,
snapPinListToTop: Bool, demoVideoChats: Bool
demoAudioStream: Bool
) { ) {
self.keepChatNavigationStack = keepChatNavigationStack self.keepChatNavigationStack = keepChatNavigationStack
self.skipReadHistory = skipReadHistory self.skipReadHistory = skipReadHistory
@ -61,8 +58,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
self.preferredVideoCodec = preferredVideoCodec self.preferredVideoCodec = preferredVideoCodec
self.disableVideoAspectScaling = disableVideoAspectScaling self.disableVideoAspectScaling = disableVideoAspectScaling
self.enableVoipTcp = enableVoipTcp self.enableVoipTcp = enableVoipTcp
self.snapPinListToTop = snapPinListToTop self.demoVideoChats = demoVideoChats
self.demoAudioStream = demoAudioStream
} }
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
@ -77,8 +73,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
self.preferredVideoCodec = decoder.decodeOptionalStringForKey("preferredVideoCodec") self.preferredVideoCodec = decoder.decodeOptionalStringForKey("preferredVideoCodec")
self.disableVideoAspectScaling = decoder.decodeInt32ForKey("disableVideoAspectScaling", orElse: 0) != 0 self.disableVideoAspectScaling = decoder.decodeInt32ForKey("disableVideoAspectScaling", orElse: 0) != 0
self.enableVoipTcp = decoder.decodeInt32ForKey("enableVoipTcp", orElse: 0) != 0 self.enableVoipTcp = decoder.decodeInt32ForKey("enableVoipTcp", orElse: 0) != 0
self.snapPinListToTop = decoder.decodeInt32ForKey("snapPinListToTop", orElse: 0) != 0 self.demoVideoChats = decoder.decodeInt32ForKey("demoVideoChats", orElse: 0) != 0
self.demoAudioStream = decoder.decodeInt32ForKey("demoAudioStream", orElse: 0) != 0
} }
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
@ -95,8 +90,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry {
} }
encoder.encodeInt32(self.disableVideoAspectScaling ? 1 : 0, forKey: "disableVideoAspectScaling") encoder.encodeInt32(self.disableVideoAspectScaling ? 1 : 0, forKey: "disableVideoAspectScaling")
encoder.encodeInt32(self.enableVoipTcp ? 1 : 0, forKey: "enableVoipTcp") encoder.encodeInt32(self.enableVoipTcp ? 1 : 0, forKey: "enableVoipTcp")
encoder.encodeInt32(self.snapPinListToTop ? 1 : 0, forKey: "snapPinListToTop") encoder.encodeInt32(self.demoVideoChats ? 1 : 0, forKey: "demoVideoChats")
encoder.encodeInt32(self.demoAudioStream ? 1 : 0, forKey: "demoAudioStream")
} }
public func isEqual(to: PreferencesEntry) -> Bool { public func isEqual(to: PreferencesEntry) -> Bool {

View File

@ -179,7 +179,7 @@ public final class OngoingGroupCallContext {
private var broadcastPartsSource: BroadcastPartSource? private var broadcastPartsSource: BroadcastPartSource?
init(queue: Queue, inputDeviceId: String, outputDeviceId: String, video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void) { init(queue: Queue, inputDeviceId: String, outputDeviceId: String, video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, enableVideo: Bool) {
self.queue = queue self.queue = queue
var networkStateUpdatedImpl: ((GroupCallNetworkState) -> Void)? var networkStateUpdatedImpl: ((GroupCallNetworkState) -> Void)?
@ -220,7 +220,9 @@ public final class OngoingGroupCallContext {
} }
return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable) return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable)
} },
outgoingAudioBitrateKbit: outgoingAudioBitrateKbit ?? 32,
enableVideo: enableVideo
) )
let queue = self.queue let queue = self.queue
@ -508,10 +510,10 @@ public final class OngoingGroupCallContext {
} }
} }
public init(inputDeviceId: String = "", outputDeviceId: String = "", video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void) { public init(inputDeviceId: String = "", outputDeviceId: String = "", video: OngoingCallVideoCapturer?, participantDescriptionsRequired: @escaping (Set<UInt32>) -> Void, audioStreamData: AudioStreamData?, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, enableVideo: Bool) {
let queue = self.queue let queue = self.queue
self.impl = QueueLocalObject(queue: queue, generate: { self.impl = QueueLocalObject(queue: queue, generate: {
return Impl(queue: queue, inputDeviceId: inputDeviceId, outputDeviceId: outputDeviceId, video: video, participantDescriptionsRequired: participantDescriptionsRequired, audioStreamData: audioStreamData, rejoinNeeded: rejoinNeeded) return Impl(queue: queue, inputDeviceId: inputDeviceId, outputDeviceId: outputDeviceId, video: video, participantDescriptionsRequired: participantDescriptionsRequired, audioStreamData: audioStreamData, rejoinNeeded: rejoinNeeded, outgoingAudioBitrateKbit: outgoingAudioBitrateKbit, enableVideo: enableVideo)
}) })
} }

View File

@ -196,7 +196,7 @@ typedef NS_ENUM(int32_t, OngoingGroupCallBroadcastPartStatus) {
@interface GroupCallThreadLocalContext : NSObject @interface GroupCallThreadLocalContext : NSObject
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart; - (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit enableVideo:(bool)enableVideo;
- (void)stop; - (void)stop;

View File

@ -854,7 +854,7 @@ private:
@implementation GroupCallThreadLocalContext @implementation GroupCallThreadLocalContext
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart { - (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue networkStateUpdated:(void (^ _Nonnull)(GroupCallNetworkState))networkStateUpdated audioLevelsUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))audioLevelsUpdated inputDeviceId:(NSString * _Nonnull)inputDeviceId outputDeviceId:(NSString * _Nonnull)outputDeviceId videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer incomingVideoSourcesUpdated:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))incomingVideoSourcesUpdated participantDescriptionsRequired:(void (^ _Nonnull)(NSArray<NSNumber *> * _Nonnull))participantDescriptionsRequired requestBroadcastPart:(id<OngoingGroupCallBroadcastPartTask> _Nonnull (^ _Nonnull)(int64_t, int64_t, void (^ _Nonnull)(OngoingGroupCallBroadcastPart * _Nullable)))requestBroadcastPart outgoingAudioBitrateKbit:(int32_t)outgoingAudioBitrateKbit enableVideo:(bool)enableVideo {
self = [super init]; self = [super init];
if (self != nil) { if (self != nil) {
_queue = queue; _queue = queue;
@ -937,7 +937,9 @@ private:
completion(std::move(parsedPart)); completion(std::move(parsedPart));
}); });
return std::make_shared<BroadcastPartTaskImpl>(task); return std::make_shared<BroadcastPartTaskImpl>(task);
} },
.outgoingAudioBitrateKbit = outgoingAudioBitrateKbit,
.enableVideo = enableVideo
})); }));
} }
return self; return self;
@ -1232,6 +1234,22 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
} }
parsedParticipants.push_back(parsedParticipant); parsedParticipants.push_back(parsedParticipant);
} }
NSDictionary *video = dict[@"video"];
if ([video isKindOfClass:[NSDictionary class]]) {
NSArray *serverSources = video[@"server_sources"];
if ([serverSources isKindOfClass:[NSArray class]]) {
for (NSNumber *sourceNumber in serverSources) {
if ([sourceNumber isKindOfClass:[NSNumber class]]) {
int32_t signedSource = [sourceNumber intValue];
result.serverVideoBandwidthProbingSsrc = *(int32_t *)&signedSource;
} else if ([sourceNumber isKindOfClass:[NSString class]]) {
uint32_t source = (uint32_t)[sourceNumber longLongValue];
result.serverVideoBandwidthProbingSsrc = source;
}
}
}
}
if (_instance) { if (_instance) {
_instance->setJoinResponsePayload(result, std::move(parsedParticipants)); _instance->setJoinResponsePayload(result, std::move(parsedParticipants));

@ -1 +1 @@
Subproject commit 194449a2dd5a2bcb56a487e691842111bf5adf5f Subproject commit 68ade13752f14fecf0b32bc08e8e47164ef52ddc