Move json processing into tgcalls [skip ci]

This commit is contained in:
Ali 2021-04-29 01:54:00 +04:00
parent 21e0eab9e4
commit 6d4bbd0b75
12 changed files with 344 additions and 643 deletions

View File

@ -3,7 +3,7 @@
@implementation Serialization @implementation Serialization
- (NSUInteger)currentLayer { - (NSUInteger)currentLayer {
return 128; return 129;
} }
- (id _Nullable)parseMessage:(NSData * _Nullable)data { - (id _Nullable)parseMessage:(NSData * _Nullable)data {

View File

@ -7,7 +7,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1255641564] = { return parseString($0) } dict[-1255641564] = { return parseString($0) }
dict[-1240849242] = { return Api.messages.StickerSet.parse_stickerSet($0) } dict[-1240849242] = { return Api.messages.StickerSet.parse_stickerSet($0) }
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) } dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
dict[-916691372] = { return Api.GroupCall.parse_groupCall($0) } dict[1698544301] = { return Api.GroupCall.parse_groupCall($0) }
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) } dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) } dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) } dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
@ -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[-1184160274] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) } dict[-1464184409] = { 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) }
@ -280,6 +280,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-206342113] = { return Api.Update.parse_updateChatParticipant($0) } dict[-206342113] = { return Api.Update.parse_updateChatParticipant($0) }
dict[2146218476] = { return Api.Update.parse_updateChannelParticipant($0) } dict[2146218476] = { return Api.Update.parse_updateChannelParticipant($0) }
dict[133777546] = { return Api.Update.parse_updateBotStopped($0) } dict[133777546] = { return Api.Update.parse_updateBotStopped($0) }
dict[192428418] = { return Api.Update.parse_updateGroupCallConnection($0) }
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) } dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) } dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }

View File

@ -1,7 +1,7 @@
public extension Api { public extension Api {
public enum GroupCall: TypeConstructorDescription { public enum GroupCall: TypeConstructorDescription {
case groupCallDiscarded(id: Int64, accessHash: Int64, duration: Int32) case groupCallDiscarded(id: Int64, accessHash: Int64, duration: Int32)
case groupCall(flags: Int32, id: Int64, accessHash: Int64, participantsCount: Int32, params: Api.DataJSON?, title: String?, streamDcId: Int32?, recordStartDate: Int32?, scheduleDate: Int32?, version: Int32) case groupCall(flags: Int32, id: Int64, accessHash: Int64, participantsCount: Int32, title: String?, streamDcId: Int32?, recordStartDate: Int32?, scheduleDate: Int32?, version: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
@ -13,15 +13,14 @@ public extension Api {
serializeInt64(accessHash, buffer: buffer, boxed: false) serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeInt32(duration, buffer: buffer, boxed: false) serializeInt32(duration, buffer: buffer, boxed: false)
break break
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let title, let streamDcId, let recordStartDate, let scheduleDate, let version): case .groupCall(let flags, let id, let accessHash, let participantsCount, let title, let streamDcId, let recordStartDate, let scheduleDate, let version):
if boxed { if boxed {
buffer.appendInt32(-916691372) buffer.appendInt32(1698544301)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false) serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false) serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeInt32(participantsCount, buffer: buffer, boxed: false) serializeInt32(participantsCount, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {params!.serialize(buffer, true)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(title!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 3) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(streamDcId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 4) != 0 {serializeInt32(streamDcId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {serializeInt32(recordStartDate!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 5) != 0 {serializeInt32(recordStartDate!, buffer: buffer, boxed: false)}
@ -35,8 +34,8 @@ public extension Api {
switch self { switch self {
case .groupCallDiscarded(let id, let accessHash, let duration): case .groupCallDiscarded(let id, let accessHash, let duration):
return ("groupCallDiscarded", [("id", id), ("accessHash", accessHash), ("duration", duration)]) return ("groupCallDiscarded", [("id", id), ("accessHash", accessHash), ("duration", duration)])
case .groupCall(let flags, let id, let accessHash, let participantsCount, let params, let title, let streamDcId, let recordStartDate, let scheduleDate, let version): case .groupCall(let flags, let id, let accessHash, let participantsCount, let title, let streamDcId, let recordStartDate, let scheduleDate, let version):
return ("groupCall", [("flags", flags), ("id", id), ("accessHash", accessHash), ("participantsCount", participantsCount), ("params", params), ("title", title), ("streamDcId", streamDcId), ("recordStartDate", recordStartDate), ("scheduleDate", scheduleDate), ("version", version)]) return ("groupCall", [("flags", flags), ("id", id), ("accessHash", accessHash), ("participantsCount", participantsCount), ("title", title), ("streamDcId", streamDcId), ("recordStartDate", recordStartDate), ("scheduleDate", scheduleDate), ("version", version)])
} }
} }
@ -66,32 +65,27 @@ public extension Api {
_3 = reader.readInt64() _3 = reader.readInt64()
var _4: Int32? var _4: Int32?
_4 = reader.readInt32() _4 = reader.readInt32()
var _5: Api.DataJSON? var _5: String?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { if Int(_1!) & Int(1 << 3) != 0 {_5 = parseString(reader) }
_5 = Api.parse(reader, signature: signature) as? Api.DataJSON var _6: Int32?
} } if Int(_1!) & Int(1 << 4) != 0 {_6 = reader.readInt32() }
var _6: String?
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
var _7: Int32? var _7: Int32?
if Int(_1!) & Int(1 << 4) != 0 {_7 = reader.readInt32() } if Int(_1!) & Int(1 << 5) != 0 {_7 = reader.readInt32() }
var _8: Int32? var _8: Int32?
if Int(_1!) & Int(1 << 5) != 0 {_8 = reader.readInt32() } if Int(_1!) & Int(1 << 7) != 0 {_8 = reader.readInt32() }
var _9: Int32? var _9: Int32?
if Int(_1!) & Int(1 << 7) != 0 {_9 = reader.readInt32() } _9 = reader.readInt32()
var _10: Int32?
_10 = reader.readInt32()
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
let _c4 = _4 != nil let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil let _c7 = (Int(_1!) & Int(1 << 5) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil let _c8 = (Int(_1!) & Int(1 << 7) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil let _c9 = _9 != nil
let _c10 = _10 != nil if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { return Api.GroupCall.groupCall(flags: _1!, id: _2!, accessHash: _3!, participantsCount: _4!, title: _5, streamDcId: _6, recordStartDate: _7, scheduleDate: _8, version: _9!)
return Api.GroupCall.groupCall(flags: _1!, id: _2!, accessHash: _3!, participantsCount: _4!, params: _5, title: _6, streamDcId: _7, recordStartDate: _8, scheduleDate: _9, version: _10!)
} }
else { else {
return nil return nil
@ -3602,13 +3596,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?, params: Api.DataJSON?) case groupCallParticipant(flags: Int32, peer: Api.Peer, date: Int32, activeDate: Int32?, source: Int32, volume: Int32?, about: String?, raiseHandRating: Int64?, video: Api.DataJSON?, presentation: 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, let params): case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about, let raiseHandRating, let video, let presentation):
if boxed { if boxed {
buffer.appendInt32(-1184160274) buffer.appendInt32(-1464184409)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
@ -3618,15 +3612,16 @@ 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)} if Int(flags) & Int(1 << 6) != 0 {video!.serialize(buffer, true)}
if Int(flags) & Int(1 << 14) != 0 {presentation!.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, let params): case .groupCallParticipant(let flags, let peer, let date, let activeDate, let source, let volume, let about, let raiseHandRating, let video, let presentation):
return ("groupCallParticipant", [("flags", flags), ("peer", peer), ("date", date), ("activeDate", activeDate), ("source", source), ("volume", volume), ("about", about), ("raiseHandRating", raiseHandRating), ("params", params)]) return ("groupCallParticipant", [("flags", flags), ("peer", peer), ("date", date), ("activeDate", activeDate), ("source", source), ("volume", volume), ("about", about), ("raiseHandRating", raiseHandRating), ("video", video), ("presentation", presentation)])
} }
} }
@ -3653,6 +3648,10 @@ public extension Api {
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.DataJSON _9 = Api.parse(reader, signature: signature) as? Api.DataJSON
} } } }
var _10: Api.DataJSON?
if Int(_1!) & Int(1 << 14) != 0 {if let signature = reader.readInt32() {
_10 = 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
@ -3662,8 +3661,9 @@ public extension Api {
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
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil
return Api.GroupCallParticipant.groupCallParticipant(flags: _1!, peer: _2!, date: _3!, activeDate: _4, source: _5!, volume: _6, about: _7, raiseHandRating: _8, params: _9) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.GroupCallParticipant.groupCallParticipant(flags: _1!, peer: _2!, date: _3!, activeDate: _4, source: _5!, volume: _6, about: _7, raiseHandRating: _8, video: _9, presentation: _10)
} }
else { else {
return nil return nil
@ -4681,6 +4681,7 @@ public extension Api {
case updateChatParticipant(flags: Int32, chatId: Int32, date: Int32, actorId: Int32, userId: Int32, prevParticipant: Api.ChatParticipant?, newParticipant: Api.ChatParticipant?, invite: Api.ExportedChatInvite?, qts: Int32) case updateChatParticipant(flags: Int32, chatId: Int32, date: Int32, actorId: Int32, userId: Int32, prevParticipant: Api.ChatParticipant?, newParticipant: Api.ChatParticipant?, invite: Api.ExportedChatInvite?, qts: Int32)
case updateChannelParticipant(flags: Int32, channelId: Int32, date: Int32, actorId: Int32, userId: Int32, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, invite: Api.ExportedChatInvite?, qts: Int32) case updateChannelParticipant(flags: Int32, channelId: Int32, date: Int32, actorId: Int32, userId: Int32, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, invite: Api.ExportedChatInvite?, qts: Int32)
case updateBotStopped(userId: Int32, date: Int32, stopped: Api.Bool, qts: Int32) case updateBotStopped(userId: Int32, date: Int32, stopped: Api.Bool, qts: Int32)
case updateGroupCallConnection(flags: Int32, params: Api.DataJSON)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
@ -5475,6 +5476,13 @@ public extension Api {
stopped.serialize(buffer, true) stopped.serialize(buffer, true)
serializeInt32(qts, buffer: buffer, boxed: false) serializeInt32(qts, buffer: buffer, boxed: false)
break break
case .updateGroupCallConnection(let flags, let params):
if boxed {
buffer.appendInt32(192428418)
}
serializeInt32(flags, buffer: buffer, boxed: false)
params.serialize(buffer, true)
break
} }
} }
@ -5662,6 +5670,8 @@ public extension Api {
return ("updateChannelParticipant", [("flags", flags), ("channelId", channelId), ("date", date), ("actorId", actorId), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("invite", invite), ("qts", qts)]) return ("updateChannelParticipant", [("flags", flags), ("channelId", channelId), ("date", date), ("actorId", actorId), ("userId", userId), ("prevParticipant", prevParticipant), ("newParticipant", newParticipant), ("invite", invite), ("qts", qts)])
case .updateBotStopped(let userId, let date, let stopped, let qts): case .updateBotStopped(let userId, let date, let stopped, let qts):
return ("updateBotStopped", [("userId", userId), ("date", date), ("stopped", stopped), ("qts", qts)]) return ("updateBotStopped", [("userId", userId), ("date", date), ("stopped", stopped), ("qts", qts)])
case .updateGroupCallConnection(let flags, let params):
return ("updateGroupCallConnection", [("flags", flags), ("params", params)])
} }
} }
@ -7281,6 +7291,22 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_updateGroupCallConnection(_ reader: BufferReader) -> Update? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.DataJSON?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.Update.updateGroupCallConnection(flags: _1!, params: _2!)
}
else {
return nil
}
}
} }
public enum PopularContact: TypeConstructorDescription { public enum PopularContact: TypeConstructorDescription {

View File

@ -7837,16 +7837,20 @@ public extension Api {
}) })
} }
public static func checkGroupCall(call: Api.InputGroupCall, source: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) { public static func checkGroupCall(call: Api.InputGroupCall, sources: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(-1219855382) buffer.appendInt32(-1248003721)
call.serialize(buffer, true) call.serialize(buffer, true)
serializeInt32(source, buffer: buffer, boxed: false) buffer.appendInt32(481674261)
return (FunctionDescription(name: "phone.checkGroupCall", parameters: [("call", call), ("source", source)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in buffer.appendInt32(Int32(sources.count))
for item in sources {
serializeInt32(item, buffer: buffer, boxed: false)
}
return (FunctionDescription(name: "phone.checkGroupCall", parameters: [("call", call), ("sources", sources)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in
let reader = BufferReader(buffer) let reader = BufferReader(buffer)
var result: Api.Bool? var result: [Int32]?
if let signature = reader.readInt32() { if let _ = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
} }
return result return result
}) })
@ -7975,6 +7979,35 @@ public extension Api {
return result return result
}) })
} }
public static func joinGroupCallPresentation(call: Api.InputGroupCall, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-873829436)
call.serialize(buffer, true)
params.serialize(buffer, true)
return (FunctionDescription(name: "phone.joinGroupCallPresentation", parameters: [("call", call), ("params", params)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
public static func leaveGroupCallPresentation(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(475058500)
call.serialize(buffer, true)
return (FunctionDescription(name: "phone.leaveGroupCallPresentation", parameters: [("call", call)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
} }
} }
} }

View File

@ -24,7 +24,20 @@ private extension GroupCallParticipantsContext.Participant {
if let ssrc = self.ssrc { if let ssrc = self.ssrc {
participantSsrcs.insert(ssrc) participantSsrcs.insert(ssrc)
} }
if let jsonParams = self.jsonParams, let jsonData = jsonParams.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] { if let jsonParams = self.videoJsonDescription, let jsonData = jsonParams.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
if let groups = json["ssrc-groups"] as? [Any] {
for group in groups {
if let group = group as? [String: Any] {
if let groupSources = group["sources"] as? [UInt32] {
for source in groupSources {
participantSsrcs.insert(source)
}
}
}
}
}
}
if let jsonParams = self.presentationJsonDescription, let jsonData = jsonParams.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
if let groups = json["ssrc-groups"] as? [Any] { if let groups = json["ssrc-groups"] as? [Any] {
for group in groups { for group in groups {
if let group = group as? [String: Any] { if let group = group as? [String: Any] {
@ -74,14 +87,14 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
id: call.id, id: call.id,
accessHash: call.accessHash, accessHash: call.accessHash,
participantCount: 0, participantCount: 0,
clientParams: nil,
streamDcId: nil, streamDcId: nil,
title: call.title, title: call.title,
scheduleTimestamp: call.scheduleTimestamp, scheduleTimestamp: call.scheduleTimestamp,
subscribedToScheduled: call.subscribedToScheduled, subscribedToScheduled: call.subscribedToScheduled,
recordingStartTimestamp: nil, recordingStartTimestamp: nil,
sortAscending: true, sortAscending: true,
defaultParticipantsAreMuted: nil defaultParticipantsAreMuted: nil,
isVideoEnabled: false
), ),
topParticipants: [], topParticipants: [],
participantCount: 0, participantCount: 0,
@ -123,7 +136,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext {
} }
return GroupCallPanelData( return GroupCallPanelData(
peerId: peerId, peerId: peerId,
info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, clientParams: nil, streamDcId: nil, title: state.title, scheduleTimestamp: state.scheduleTimestamp, subscribedToScheduled: state.subscribedToScheduled, recordingStartTimestamp: nil, sortAscending: state.sortAscending, defaultParticipantsAreMuted: state.defaultParticipantsAreMuted), info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, streamDcId: nil, title: state.title, scheduleTimestamp: state.scheduleTimestamp, subscribedToScheduled: state.subscribedToScheduled, recordingStartTimestamp: nil, sortAscending: state.sortAscending, defaultParticipantsAreMuted: state.defaultParticipantsAreMuted, isVideoEnabled: state.isVideoEnabled),
topParticipants: topParticipants, topParticipants: topParticipants,
participantCount: state.totalCount, participantCount: state.totalCount,
activeSpeakers: activeSpeakers, activeSpeakers: activeSpeakers,
@ -698,7 +711,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return return
} }
if case let .established(callInfo, _, _, _, _) = strongSelf.internalState { if case let .established(callInfo, _, _, _, _) = strongSelf.internalState {
var addedParticipants: [(UInt32, String?)] = [] var addedParticipants: [(UInt32, String?, String?)] = []
var removedSsrc: [UInt32] = [] var removedSsrc: [UInt32] = []
for (callId, update) in updates { for (callId, update) in updates {
if callId == callInfo.id { if callId == callInfo.id {
@ -734,13 +747,13 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
} }
} else if case .joined = participantUpdate.participationStatusChange { } else if case .joined = participantUpdate.participationStatusChange {
if let ssrc = participantUpdate.ssrc { if let ssrc = participantUpdate.ssrc {
addedParticipants.append((ssrc, participantUpdate.jsonParams)) addedParticipants.append((ssrc, participantUpdate.videoJsonDescription, participantUpdate.presentationJsonDescription))
} }
} else if let ssrc = participantUpdate.ssrc, strongSelf.ssrcMapping[ssrc] == nil { } else if let ssrc = participantUpdate.ssrc, strongSelf.ssrcMapping[ssrc] == nil {
addedParticipants.append((ssrc, participantUpdate.jsonParams)) addedParticipants.append((ssrc, participantUpdate.videoJsonDescription, participantUpdate.presentationJsonDescription))
} }
} }
case let .call(isTerminated, _, _, _, _): case let .call(isTerminated, _, _, _, _, _):
if isTerminated { if isTerminated {
strongSelf.markAsCanBeRemoved() strongSelf.markAsCanBeRemoved()
} }
@ -750,7 +763,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
if !removedSsrc.isEmpty { if !removedSsrc.isEmpty {
strongSelf.callContext?.removeSsrcs(ssrcs: removedSsrc) strongSelf.callContext?.removeSsrcs(ssrcs: removedSsrc)
} }
//strongSelf.callContext?.addParticipants(participants: addedParticipants)
} }
}) })
@ -924,14 +936,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
participants.append(GroupCallParticipantsContext.Participant( participants.append(GroupCallParticipantsContext.Participant(
peer: myPeer, peer: myPeer,
ssrc: nil, ssrc: nil,
jsonParams: nil, videoJsonDescription: nil,
presentationJsonDescription: nil,
joinTimestamp: strongSelf.temporaryJoinTimestamp, joinTimestamp: strongSelf.temporaryJoinTimestamp,
raiseHandRating: strongSelf.temporaryRaiseHandRating, raiseHandRating: strongSelf.temporaryRaiseHandRating,
hasRaiseHand: strongSelf.temporaryHasRaiseHand, hasRaiseHand: strongSelf.temporaryHasRaiseHand,
activityTimestamp: strongSelf.temporaryActivityTimestamp, activityTimestamp: strongSelf.temporaryActivityTimestamp,
activityRank: strongSelf.temporaryActivityRank, activityRank: strongSelf.temporaryActivityRank,
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
isVideoMuted: true,
volume: nil, volume: nil,
about: about about: about
)) ))
@ -1005,14 +1017,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
participants.append(GroupCallParticipantsContext.Participant( participants.append(GroupCallParticipantsContext.Participant(
peer: myPeer, peer: myPeer,
ssrc: nil, ssrc: nil,
jsonParams: nil, videoJsonDescription: nil,
presentationJsonDescription: nil,
joinTimestamp: strongSelf.temporaryJoinTimestamp, joinTimestamp: strongSelf.temporaryJoinTimestamp,
raiseHandRating: strongSelf.temporaryRaiseHandRating, raiseHandRating: strongSelf.temporaryRaiseHandRating,
hasRaiseHand: strongSelf.temporaryHasRaiseHand, hasRaiseHand: strongSelf.temporaryHasRaiseHand,
activityTimestamp: strongSelf.temporaryActivityTimestamp, activityTimestamp: strongSelf.temporaryActivityTimestamp,
activityRank: strongSelf.temporaryActivityRank, activityRank: strongSelf.temporaryActivityRank,
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
isVideoMuted: true,
volume: nil, volume: nil,
about: about about: about
)) ))
@ -1114,6 +1126,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
scheduleTimestamp: self.stateValue.scheduleTimestamp, scheduleTimestamp: self.stateValue.scheduleTimestamp,
subscribedToScheduled: self.stateValue.subscribedToScheduled, subscribedToScheduled: self.stateValue.subscribedToScheduled,
totalCount: 0, totalCount: 0,
isVideoEnabled: false,
version: 0 version: 0
), ),
previousServiceState: nil previousServiceState: nil
@ -1168,14 +1181,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
participants.append(GroupCallParticipantsContext.Participant( participants.append(GroupCallParticipantsContext.Participant(
peer: myPeer, peer: myPeer,
ssrc: nil, ssrc: nil,
jsonParams: nil, videoJsonDescription: nil,
presentationJsonDescription: nil,
joinTimestamp: strongSelf.temporaryJoinTimestamp, joinTimestamp: strongSelf.temporaryJoinTimestamp,
raiseHandRating: strongSelf.temporaryRaiseHandRating, raiseHandRating: strongSelf.temporaryRaiseHandRating,
hasRaiseHand: strongSelf.temporaryHasRaiseHand, hasRaiseHand: strongSelf.temporaryHasRaiseHand,
activityTimestamp: strongSelf.temporaryActivityTimestamp, activityTimestamp: strongSelf.temporaryActivityTimestamp,
activityRank: strongSelf.temporaryActivityRank, activityRank: strongSelf.temporaryActivityRank,
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canManageCall || !state.defaultParticipantsAreMuted.isMuted, mutedByYou: false), muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canManageCall || !state.defaultParticipantsAreMuted.isMuted, mutedByYou: false),
isVideoMuted: true,
volume: nil, volume: nil,
about: about about: about
)) ))
@ -1200,20 +1213,20 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.stateValue.scheduleTimestamp = strongSelf.isScheduledStarted ? nil : state.scheduleTimestamp strongSelf.stateValue.scheduleTimestamp = strongSelf.isScheduledStarted ? nil : state.scheduleTimestamp
if state.scheduleTimestamp == nil && !strongSelf.isScheduledStarted { if state.scheduleTimestamp == nil && !strongSelf.isScheduledStarted {
strongSelf.updateSessionState(internalState: .active(GroupCallInfo(id: callInfo.id, accessHash: callInfo.accessHash, participantCount: state.totalCount, clientParams: callInfo.clientParams, streamDcId: callInfo.streamDcId, title: state.title, scheduleTimestamp: nil, subscribedToScheduled: false, recordingStartTimestamp: nil, sortAscending: true, defaultParticipantsAreMuted: callInfo.defaultParticipantsAreMuted ?? state.defaultParticipantsAreMuted)), audioSessionControl: strongSelf.audioSessionControl) strongSelf.updateSessionState(internalState: .active(GroupCallInfo(id: callInfo.id, accessHash: callInfo.accessHash, participantCount: state.totalCount, streamDcId: callInfo.streamDcId, title: state.title, scheduleTimestamp: nil, subscribedToScheduled: false, recordingStartTimestamp: nil, sortAscending: true, defaultParticipantsAreMuted: callInfo.defaultParticipantsAreMuted ?? state.defaultParticipantsAreMuted, isVideoEnabled: callInfo.isVideoEnabled)), audioSessionControl: strongSelf.audioSessionControl)
} else { } else {
strongSelf.summaryInfoState.set(.single(SummaryInfoState(info: GroupCallInfo( strongSelf.summaryInfoState.set(.single(SummaryInfoState(info: GroupCallInfo(
id: callInfo.id, id: callInfo.id,
accessHash: callInfo.accessHash, accessHash: callInfo.accessHash,
participantCount: state.totalCount, participantCount: state.totalCount,
clientParams: nil,
streamDcId: nil, streamDcId: nil,
title: state.title, title: state.title,
scheduleTimestamp: state.scheduleTimestamp, scheduleTimestamp: state.scheduleTimestamp,
subscribedToScheduled: false, subscribedToScheduled: false,
recordingStartTimestamp: state.recordingStartTimestamp, recordingStartTimestamp: state.recordingStartTimestamp,
sortAscending: state.sortAscending, sortAscending: state.sortAscending,
defaultParticipantsAreMuted: state.defaultParticipantsAreMuted defaultParticipantsAreMuted: state.defaultParticipantsAreMuted,
isVideoEnabled: state.isVideoEnabled
)))) ))))
strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState(
@ -1389,28 +1402,26 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if let clientParams = joinCallResult.callInfo.clientParams { let clientParams = joinCallResult.jsonParams
strongSelf.ssrcMapping.removeAll()
let addedParticipants: [(UInt32, String?)] = [] strongSelf.ssrcMapping.removeAll()
for participant in joinCallResult.state.participants { for participant in joinCallResult.state.participants {
if let ssrc = participant.ssrc { if let ssrc = participant.ssrc {
strongSelf.ssrcMapping[ssrc] = participant.peer.id strongSelf.ssrcMapping[ssrc] = participant.peer.id
//addedParticipants.append((participant.ssrc, participant.jsonParams))
}
} }
switch joinCallResult.connectionMode {
case .rtc:
strongSelf.currentConnectionMode = .rtc
strongSelf.callContext?.setConnectionMode(.rtc, keepBroadcastConnectedIfWasEnabled: false)
strongSelf.callContext?.setJoinResponse(payload: clientParams, participants: addedParticipants)
case .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)
} }
switch joinCallResult.connectionMode {
case .rtc:
strongSelf.currentConnectionMode = .rtc
strongSelf.callContext?.setConnectionMode(.rtc, keepBroadcastConnectedIfWasEnabled: false)
strongSelf.callContext?.setJoinResponse(payload: clientParams)
case .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)
}, error: { error in }, error: { error in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
@ -1743,14 +1754,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
participants.append(GroupCallParticipantsContext.Participant( participants.append(GroupCallParticipantsContext.Participant(
peer: myPeer, peer: myPeer,
ssrc: nil, ssrc: nil,
jsonParams: nil, videoJsonDescription: nil,
presentationJsonDescription: nil,
joinTimestamp: strongSelf.temporaryJoinTimestamp, joinTimestamp: strongSelf.temporaryJoinTimestamp,
raiseHandRating: strongSelf.temporaryRaiseHandRating, raiseHandRating: strongSelf.temporaryRaiseHandRating,
hasRaiseHand: strongSelf.temporaryHasRaiseHand, hasRaiseHand: strongSelf.temporaryHasRaiseHand,
activityTimestamp: strongSelf.temporaryActivityTimestamp, activityTimestamp: strongSelf.temporaryActivityTimestamp,
activityRank: strongSelf.temporaryActivityRank, activityRank: strongSelf.temporaryActivityRank,
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false), muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
isVideoMuted: true,
volume: nil, volume: nil,
about: about about: about
)) ))
@ -1852,7 +1863,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
} else if participant.muteState?.mutedByYou == true { } else if participant.muteState?.mutedByYou == true {
strongSelf.callContext?.setVolume(ssrc: ssrc, volume: 0.0) strongSelf.callContext?.setVolume(ssrc: ssrc, volume: 0.0)
} }
if participant.isVideoMuted { if participant.videoJsonDescription == nil {
strongSelf.callContext?.removeIncomingVideoSource(ssrc) strongSelf.callContext?.removeIncomingVideoSource(ssrc)
} }
} }
@ -1885,14 +1896,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
id: callInfo.id, id: callInfo.id,
accessHash: callInfo.accessHash, accessHash: callInfo.accessHash,
participantCount: state.totalCount, participantCount: state.totalCount,
clientParams: nil,
streamDcId: nil, streamDcId: nil,
title: state.title, title: state.title,
scheduleTimestamp: state.scheduleTimestamp, scheduleTimestamp: state.scheduleTimestamp,
subscribedToScheduled: false, subscribedToScheduled: false,
recordingStartTimestamp: state.recordingStartTimestamp, recordingStartTimestamp: state.recordingStartTimestamp,
sortAscending: state.sortAscending, sortAscending: state.sortAscending,
defaultParticipantsAreMuted: state.defaultParticipantsAreMuted defaultParticipantsAreMuted: state.defaultParticipantsAreMuted,
isVideoEnabled: state.isVideoEnabled
)))) ))))
strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState( strongSelf.summaryParticipantsState.set(.single(SummaryParticipantsState(
@ -1949,7 +1960,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private func maybeRequestParticipants(ssrcs: Set<UInt32>) { private func maybeRequestParticipants(ssrcs: Set<UInt32>) {
var addedMissingSsrcs = ssrcs var addedMissingSsrcs = ssrcs
var addedParticipants: [(UInt32, String?)] = [] var addedParticipants: [(UInt32, String?, String?)] = []
if let membersValue = self.membersValue { if let membersValue = self.membersValue {
for participant in membersValue.participants { for participant in membersValue.participants {
@ -1959,7 +1970,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
addedMissingSsrcs.subtract(participantSsrcs) addedMissingSsrcs.subtract(participantSsrcs)
if let ssrc = participant.ssrc { if let ssrc = participant.ssrc {
addedParticipants.append((ssrc, participant.jsonParams)) addedParticipants.append((ssrc, participant.videoJsonDescription, participant.presentationJsonDescription))
} }
} }
} }
@ -1994,22 +2005,22 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
strongSelf.isRequestingMissingSsrcs = false strongSelf.isRequestingMissingSsrcs = false
strongSelf.missingSsrcs.subtract(requestedSsrcs) strongSelf.missingSsrcs.subtract(requestedSsrcs)
var addedParticipants: [(UInt32, Int32?, String?)] = [] var addedParticipants: [(UInt32, Int32?, String?, String?)] = []
for participant in state.participants { for participant in state.participants {
if let ssrc = participant.ssrc { if let ssrc = participant.ssrc {
addedParticipants.append((ssrc, participant.volume, participant.jsonParams)) addedParticipants.append((ssrc, participant.volume, participant.videoJsonDescription, participant.presentationJsonDescription))
} }
} }
if !addedParticipants.isEmpty { if !addedParticipants.isEmpty {
for (ssrc, volume, _) in addedParticipants { for (ssrc, volume, _, _) in addedParticipants {
if let volume = volume { if let volume = volume {
strongSelf.callContext?.setVolume(ssrc: ssrc, volume: Double(volume) / 10000.0) strongSelf.callContext?.setVolume(ssrc: ssrc, volume: Double(volume) / 10000.0)
} }
} }
strongSelf.callContext?.addParticipants(participants: addedParticipants.map { ssrc, _, params in strongSelf.callContext?.addParticipants(participants: addedParticipants.map { ssrc, _, videoParams, presentationParams in
return (ssrc, params) return (ssrc, videoParams, presentationParams)
}) })
} }
@ -2023,14 +2034,21 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
return return
} }
if case let .established(callInfo, connectionMode, _, ssrc, _) = self.internalState, case .rtc = connectionMode { if case let .established(callInfo, connectionMode, _, ssrc, _) = self.internalState, case .rtc = connectionMode {
let checkSignal = checkGroupCall(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, ssrc: Int32(bitPattern: ssrc)) let checkSignal = checkGroupCall(account: self.account, callId: callInfo.id, accessHash: callInfo.accessHash, ssrcs: [ssrc])
self.checkCallDisposable = (( self.checkCallDisposable = ((
checkSignal checkSignal
|> castError(Bool.self) |> castError(Bool.self)
|> delay(4.0, queue: .mainQueue()) |> delay(4.0, queue: .mainQueue())
|> mapToSignal { result -> Signal<Bool, Bool> in |> mapToSignal { result -> Signal<Bool, Bool> in
if case .success = result { var foundAll = true
for value in [ssrc] {
if !result.contains(value) {
foundAll = false
break
}
}
if foundAll {
return .fail(true) return .fail(true)
} else { } else {
return .single(true) return .single(true)
@ -2354,7 +2372,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
if id == peerId { if id == peerId {
self.callContext?.setVolume(ssrc: ssrc, volume: Double(volume) / 10000.0) self.callContext?.setVolume(ssrc: ssrc, volume: Double(volume) / 10000.0)
if sync { if sync {
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, isVideoMuted: nil, volume: volume, raiseHand: nil) self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: volume, raiseHand: nil)
} }
break break
} }
@ -2462,19 +2480,19 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
canThenUnmute = true canThenUnmute = true
} }
let muteState = isMuted ? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canThenUnmute, mutedByYou: mutedByYou) : nil let muteState = isMuted ? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canThenUnmute, mutedByYou: mutedByYou) : nil
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, isVideoMuted: nil, volume: nil, raiseHand: nil) self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil, raiseHand: nil)
return muteState return muteState
} else { } else {
if peerId == self.joinAsPeerId { if peerId == self.joinAsPeerId {
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: nil) self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil, raiseHand: nil)
return nil return nil
} else if self.stateValue.canManageCall || self.stateValue.adminIds.contains(self.accountContext.account.peerId) { } else if self.stateValue.canManageCall || self.stateValue.adminIds.contains(self.accountContext.account.peerId) {
let muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false) let muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false)
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, isVideoMuted: nil, volume: nil, raiseHand: nil) self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil, raiseHand: nil)
return muteState return muteState
} else { } else {
self.setVolume(peerId: peerId, volume: 10000, sync: true) self.setVolume(peerId: peerId, volume: 10000, sync: true)
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: nil) self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil, raiseHand: nil)
return nil return nil
} }
} }

View File

@ -8,7 +8,6 @@ public struct GroupCallInfo: Equatable {
public var id: Int64 public var id: Int64
public var accessHash: Int64 public var accessHash: Int64
public var participantCount: Int public var participantCount: Int
public var clientParams: String?
public var streamDcId: Int32? public var streamDcId: Int32?
public var title: String? public var title: String?
public var scheduleTimestamp: Int32? public var scheduleTimestamp: Int32?
@ -16,24 +15,24 @@ public struct GroupCallInfo: Equatable {
public var recordingStartTimestamp: Int32? public var recordingStartTimestamp: Int32?
public var sortAscending: Bool public var sortAscending: Bool
public var defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted? public var defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?
public var isVideoEnabled: Bool
public init( public init(
id: Int64, id: Int64,
accessHash: Int64, accessHash: Int64,
participantCount: Int, participantCount: Int,
clientParams: String?,
streamDcId: Int32?, streamDcId: Int32?,
title: String?, title: String?,
scheduleTimestamp: Int32?, scheduleTimestamp: Int32?,
subscribedToScheduled: Bool, subscribedToScheduled: Bool,
recordingStartTimestamp: Int32?, recordingStartTimestamp: Int32?,
sortAscending: Bool, sortAscending: Bool,
defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted? defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?,
isVideoEnabled: Bool
) { ) {
self.id = id self.id = id
self.accessHash = accessHash self.accessHash = accessHash
self.participantCount = participantCount self.participantCount = participantCount
self.clientParams = clientParams
self.streamDcId = streamDcId self.streamDcId = streamDcId
self.title = title self.title = title
self.scheduleTimestamp = scheduleTimestamp self.scheduleTimestamp = scheduleTimestamp
@ -41,6 +40,7 @@ public struct GroupCallInfo: Equatable {
self.recordingStartTimestamp = recordingStartTimestamp self.recordingStartTimestamp = recordingStartTimestamp
self.sortAscending = sortAscending self.sortAscending = sortAscending
self.defaultParticipantsAreMuted = defaultParticipantsAreMuted self.defaultParticipantsAreMuted = defaultParticipantsAreMuted
self.isVideoEnabled = isVideoEnabled
} }
} }
@ -52,26 +52,19 @@ public struct GroupCallSummary: Equatable {
extension GroupCallInfo { extension GroupCallInfo {
init?(_ call: Api.GroupCall) { init?(_ call: Api.GroupCall) {
switch call { switch call {
case let .groupCall(flags, id, accessHash, participantCount, params, title, streamDcId, recordStartDate, scheduleDate, _): case let .groupCall(flags, id, accessHash, participantsCount, title, streamDcId, recordStartDate, scheduleDate, _):
var clientParams: String?
if let params = params {
switch params {
case let .dataJSON(data):
clientParams = data
}
}
self.init( self.init(
id: id, id: id,
accessHash: accessHash, accessHash: accessHash,
participantCount: Int(participantCount), participantCount: Int(participantsCount),
clientParams: clientParams,
streamDcId: streamDcId, streamDcId: streamDcId,
title: title, title: title,
scheduleTimestamp: scheduleDate, scheduleTimestamp: scheduleDate,
subscribedToScheduled: (flags & (1 << 8)) != 0, subscribedToScheduled: (flags & (1 << 8)) != 0,
recordingStartTimestamp: recordStartDate, recordingStartTimestamp: recordStartDate,
sortAscending: (flags & (1 << 6)) != 0, sortAscending: (flags & (1 << 6)) != 0,
defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: (flags & (1 << 1)) != 0, canChange: (flags & (1 << 2)) != 0) defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: (flags & (1 << 1)) != 0, canChange: (flags & (1 << 2)) != 0),
isVideoEnabled: (flags & (1 << 9)) != 0
) )
case .groupCallDiscarded: case .groupCallDiscarded:
return nil return nil
@ -133,8 +126,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, params): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, video, presentation):
//let params: Api.DataJSON? = nil
let peerId: PeerId = apiPeerId.peerId let peerId: PeerId = apiPeerId.peerId
let ssrc = UInt32(bitPattern: source) let ssrc = UInt32(bitPattern: source)
@ -150,25 +142,31 @@ 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)
} }
var jsonParams: String? = nil var videoJsonDescription: String? = nil
if let params = params { var presentationJsonDescription: String? = nil
switch params { if let video = video {
switch video {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data videoJsonDescription = data
}
}
if let presentation = presentation {
switch presentation {
case let .dataJSON(data):
presentationJsonDescription = data
} }
} }
let isVideoMuted = (flags & (1 << 14)) != 0
parsedParticipants.append(GroupCallParticipantsContext.Participant( parsedParticipants.append(GroupCallParticipantsContext.Participant(
peer: peer, peer: peer,
ssrc: ssrc, ssrc: ssrc,
jsonParams: jsonParams, videoJsonDescription: videoJsonDescription,
presentationJsonDescription: presentationJsonDescription,
joinTimestamp: date, joinTimestamp: date,
raiseHandRating: raiseHandRating, raiseHandRating: raiseHandRating,
hasRaiseHand: raiseHandRating != nil, hasRaiseHand: raiseHandRating != nil,
activityTimestamp: activeDate.flatMap(Double.init), activityTimestamp: activeDate.flatMap(Double.init),
activityRank: nil, activityRank: nil,
muteState: muteState, muteState: muteState,
isVideoMuted: isVideoMuted,
volume: volume, volume: volume,
about: about about: about
)) ))
@ -451,8 +449,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, params): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, video, presentation):
//let params: Api.DataJSON? = nil
let peerId: PeerId = apiPeerId.peerId let peerId: PeerId = apiPeerId.peerId
let ssrc = UInt32(bitPattern: source) let ssrc = UInt32(bitPattern: source)
guard let peer = transaction.getPeer(peerId) else { guard let peer = transaction.getPeer(peerId) else {
@ -467,25 +464,31 @@ 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)
} }
var jsonParams: String? = nil var videoJsonDescription: String? = nil
if let params = params { var presentationJsonDescription: String? = nil
switch params { if let video = video {
switch video {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data videoJsonDescription = data
}
}
if let presentation = presentation {
switch presentation {
case let .dataJSON(data):
presentationJsonDescription = data
} }
} }
let isVideoMuted = (flags & (1 << 14)) != 0
parsedParticipants.append(GroupCallParticipantsContext.Participant( parsedParticipants.append(GroupCallParticipantsContext.Participant(
peer: peer, peer: peer,
ssrc: ssrc, ssrc: ssrc,
jsonParams: jsonParams, videoJsonDescription: videoJsonDescription,
presentationJsonDescription: presentationJsonDescription,
joinTimestamp: date, joinTimestamp: date,
raiseHandRating: raiseHandRating, raiseHandRating: raiseHandRating,
hasRaiseHand: raiseHandRating != nil, hasRaiseHand: raiseHandRating != nil,
activityTimestamp: activeDate.flatMap(Double.init), activityTimestamp: activeDate.flatMap(Double.init),
activityRank: nil, activityRank: nil,
muteState: muteState, muteState: muteState,
isVideoMuted: isVideoMuted,
volume: volume, volume: volume,
about: about about: about
)) ))
@ -507,6 +510,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
scheduleTimestamp: scheduleTimestamp, scheduleTimestamp: scheduleTimestamp,
subscribedToScheduled: subscribedToScheduled, subscribedToScheduled: subscribedToScheduled,
totalCount: totalCount, totalCount: totalCount,
isVideoEnabled: false,
version: version version: version
) )
} }
@ -530,6 +534,7 @@ public struct JoinGroupCallResult {
public var callInfo: GroupCallInfo public var callInfo: GroupCallInfo
public var state: GroupCallParticipantsContext.State public var state: GroupCallParticipantsContext.State
public var connectionMode: ConnectionMode public var connectionMode: ConnectionMode
public var jsonParams: String
} }
public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal<JoinGroupCallResult, JoinGroupCallError> { public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, callId: Int64, accessHash: Int64, preferMuted: Bool, joinPayload: String, peerAdminIds: Signal<[PeerId], NoError>, inviteHash: String? = nil) -> Signal<JoinGroupCallResult, JoinGroupCallError> {
@ -624,30 +629,36 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
account.stateManager.addUpdates(updates) account.stateManager.addUpdates(updates)
var maybeParsedCall: GroupCallInfo? var maybeParsedCall: GroupCallInfo?
var maybeParsedClientParams: String?
loop: for update in updates.allUpdates { loop: for update in updates.allUpdates {
switch update { switch update {
case let .updateGroupCall(_, call): case let .updateGroupCall(_, call):
maybeParsedCall = GroupCallInfo(call) maybeParsedCall = GroupCallInfo(call)
switch call { switch call {
case let .groupCall(flags, _, _, _, _, title, _, recordStartDate, scheduleDate, _): case let .groupCall(flags, _, _, _, title, _, recordStartDate, scheduleDate, _):
let isMuted = (flags & (1 << 1)) != 0 let isMuted = (flags & (1 << 1)) != 0
let canChange = (flags & (1 << 2)) != 0 let canChange = (flags & (1 << 2)) != 0
let isVideoEnabled = (flags & (1 << 9)) != 0
state.defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange) state.defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
state.title = title state.title = title
state.recordingStartTimestamp = recordStartDate state.recordingStartTimestamp = recordStartDate
state.scheduleTimestamp = scheduleDate state.scheduleTimestamp = scheduleDate
state.isVideoEnabled = isVideoEnabled
default: default:
break break
} }
case let .updateGroupCallConnection(_, params):
break loop switch params {
case let .dataJSON(data):
maybeParsedClientParams = data
}
default: default:
break break
} }
} }
guard let parsedCall = maybeParsedCall else { guard let parsedCall = maybeParsedCall, let parsedClientParams = maybeParsedClientParams else {
return .fail(.generic) return .fail(.generic)
} }
@ -669,7 +680,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
} }
let connectionMode: JoinGroupCallResult.ConnectionMode let connectionMode: JoinGroupCallResult.ConnectionMode
if let clientParams = parsedCall.clientParams, let clientParamsData = clientParams.data(using: .utf8), let dict = (try? JSONSerialization.jsonObject(with: clientParamsData, options: [])) as? [String: Any] { if let clientParamsData = parsedClientParams.data(using: .utf8), let dict = (try? JSONSerialization.jsonObject(with: clientParamsData, options: [])) as? [String: Any] {
if let stream = dict["stream"] as? Bool, stream { if let stream = dict["stream"] as? Bool, stream {
connectionMode = .broadcast connectionMode = .broadcast
} else { } else {
@ -697,8 +708,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, params): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, video, presentation):
//let params: Api.DataJSON? = nil
let peerId: PeerId = apiPeerId.peerId let peerId: PeerId = apiPeerId.peerId
let ssrc = UInt32(bitPattern: source) let ssrc = UInt32(bitPattern: source)
guard let peer = transaction.getPeer(peerId) else { guard let peer = transaction.getPeer(peerId) else {
@ -713,26 +723,32 @@ 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)
} }
var jsonParams: String? = nil var videoJsonDescription: String? = nil
if let params = params { var presentationJsonDescription: String? = nil
switch params { if let video = video {
switch video {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data videoJsonDescription = data
}
}
if let presentation = presentation {
switch presentation {
case let .dataJSON(data):
presentationJsonDescription = data
} }
} }
let isVideoMuted = (flags & (1 << 14)) != 0
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,
ssrc: ssrc, ssrc: ssrc,
jsonParams: jsonParams, videoJsonDescription: videoJsonDescription,
presentationJsonDescription: presentationJsonDescription,
joinTimestamp: date, joinTimestamp: date,
raiseHandRating: raiseHandRating, raiseHandRating: raiseHandRating,
hasRaiseHand: raiseHandRating != nil, hasRaiseHand: raiseHandRating != nil,
activityTimestamp: activeDate.flatMap(Double.init), activityTimestamp: activeDate.flatMap(Double.init),
activityRank: nil, activityRank: nil,
muteState: muteState, muteState: muteState,
isVideoMuted: isVideoMuted,
volume: volume, volume: volume,
about: about about: about
)) ))
@ -754,7 +770,8 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
return JoinGroupCallResult( return JoinGroupCallResult(
callInfo: parsedCall, callInfo: parsedCall,
state: state, state: state,
connectionMode: connectionMode connectionMode: connectionMode,
jsonParams: parsedClientParams
) )
} }
|> castError(JoinGroupCallError.self) |> castError(JoinGroupCallError.self)
@ -826,26 +843,13 @@ public func stopGroupCall(account: Account, peerId: PeerId, callId: Int64, acces
} }
} }
public enum CheckGroupCallResult { public func checkGroupCall(account: Account, callId: Int64, accessHash: Int64, ssrcs: [UInt32]) -> Signal<[UInt32], NoError> {
case success return account.network.request(Api.functions.phone.checkGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), sources: ssrcs.map(Int32.init(bitPattern:))))
case restart |> `catch` { _ -> Signal<[Int32], NoError> in
} return .single([])
public func checkGroupCall(account: Account, callId: Int64, accessHash: Int64, ssrc: Int32) -> Signal<CheckGroupCallResult, NoError> {
return account.network.request(Api.functions.phone.checkGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash), source: ssrc))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
} }
|> map { result -> CheckGroupCallResult in |> map { result -> [UInt32] in
#if DEBUG return result.map(UInt32.init(bitPattern:))
//return .restart
#endif
switch result {
case .boolTrue:
return .success
case .boolFalse:
return .restart
}
} }
} }
@ -879,41 +883,41 @@ public final class GroupCallParticipantsContext {
public var peer: Peer public var peer: Peer
public var ssrc: UInt32? public var ssrc: UInt32?
public var jsonParams: String? public var videoJsonDescription: String?
public var presentationJsonDescription: String?
public var joinTimestamp: Int32 public var joinTimestamp: Int32
public var raiseHandRating: Int64? public var raiseHandRating: Int64?
public var hasRaiseHand: Bool 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?
public var isVideoMuted: Bool
public var volume: Int32? public var volume: Int32?
public var about: String? public var about: String?
public init( public init(
peer: Peer, peer: Peer,
ssrc: UInt32?, ssrc: UInt32?,
jsonParams: String?, videoJsonDescription: String?,
presentationJsonDescription: String?,
joinTimestamp: Int32, joinTimestamp: Int32,
raiseHandRating: Int64?, raiseHandRating: Int64?,
hasRaiseHand: Bool, hasRaiseHand: Bool,
activityTimestamp: Double?, activityTimestamp: Double?,
activityRank: Int?, activityRank: Int?,
muteState: MuteState?, muteState: MuteState?,
isVideoMuted: Bool,
volume: Int32?, volume: Int32?,
about: String? about: String?
) { ) {
self.peer = peer self.peer = peer
self.ssrc = ssrc self.ssrc = ssrc
self.jsonParams = jsonParams self.videoJsonDescription = videoJsonDescription
self.presentationJsonDescription = presentationJsonDescription
self.joinTimestamp = joinTimestamp self.joinTimestamp = joinTimestamp
self.raiseHandRating = raiseHandRating self.raiseHandRating = raiseHandRating
self.hasRaiseHand = hasRaiseHand self.hasRaiseHand = hasRaiseHand
self.activityTimestamp = activityTimestamp self.activityTimestamp = activityTimestamp
self.activityRank = activityRank self.activityRank = activityRank
self.muteState = muteState self.muteState = muteState
self.isVideoMuted = isVideoMuted
self.volume = volume self.volume = volume
self.about = about self.about = about
} }
@ -936,6 +940,12 @@ public final class GroupCallParticipantsContext {
if lhs.ssrc != rhs.ssrc { if lhs.ssrc != rhs.ssrc {
return false return false
} }
if lhs.videoJsonDescription != rhs.videoJsonDescription {
return false
}
if lhs.presentationJsonDescription != rhs.presentationJsonDescription {
return false
}
if lhs.joinTimestamp != rhs.joinTimestamp { if lhs.joinTimestamp != rhs.joinTimestamp {
return false return false
} }
@ -954,9 +964,6 @@ public final class GroupCallParticipantsContext {
if lhs.muteState != rhs.muteState { if lhs.muteState != rhs.muteState {
return false return false
} }
if lhs.isVideoMuted != rhs.isVideoMuted {
return false
}
if lhs.volume != rhs.volume { if lhs.volume != rhs.volume {
return false return false
} }
@ -1040,6 +1047,7 @@ public final class GroupCallParticipantsContext {
public var scheduleTimestamp: Int32? public var scheduleTimestamp: Int32?
public var subscribedToScheduled: Bool public var subscribedToScheduled: Bool
public var totalCount: Int public var totalCount: Int
public var isVideoEnabled: Bool
public var version: Int32 public var version: Int32
public mutating func mergeActivity(from other: State, myPeerId: PeerId?, previousMyPeerId: PeerId?, mergeActivityTimestamps: Bool) { public mutating func mergeActivity(from other: State, myPeerId: PeerId?, previousMyPeerId: PeerId?, mergeActivityTimestamps: Bool) {
@ -1072,6 +1080,7 @@ public final class GroupCallParticipantsContext {
scheduleTimestamp: Int32?, scheduleTimestamp: Int32?,
subscribedToScheduled: Bool, subscribedToScheduled: Bool,
totalCount: Int, totalCount: Int,
isVideoEnabled: Bool,
version: Int32 version: Int32
) { ) {
self.participants = participants self.participants = participants
@ -1085,6 +1094,7 @@ public final class GroupCallParticipantsContext {
self.scheduleTimestamp = scheduleTimestamp self.scheduleTimestamp = scheduleTimestamp
self.subscribedToScheduled = subscribedToScheduled self.subscribedToScheduled = subscribedToScheduled
self.totalCount = totalCount self.totalCount = totalCount
self.isVideoEnabled = isVideoEnabled
self.version = version self.version = version
} }
} }
@ -1135,12 +1145,12 @@ public final class GroupCallParticipantsContext {
public var peerId: PeerId public var peerId: PeerId
public var ssrc: UInt32? public var ssrc: UInt32?
public var jsonParams: String? public var videoJsonDescription: String?
public var presentationJsonDescription: String?
public var joinTimestamp: Int32 public var joinTimestamp: Int32
public var activityTimestamp: Double? public var activityTimestamp: Double?
public var raiseHandRating: Int64? public var raiseHandRating: Int64?
public var muteState: Participant.MuteState? public var muteState: Participant.MuteState?
public var isVideoMuted: Bool
public var participationStatusChange: ParticipationStatusChange public var participationStatusChange: ParticipationStatusChange
public var volume: Int32? public var volume: Int32?
public var about: String? public var about: String?
@ -1149,12 +1159,12 @@ public final class GroupCallParticipantsContext {
init( init(
peerId: PeerId, peerId: PeerId,
ssrc: UInt32?, ssrc: UInt32?,
jsonParams: String?, videoJsonDescription: String?,
presentationJsonDescription: String?,
joinTimestamp: Int32, joinTimestamp: Int32,
activityTimestamp: Double?, activityTimestamp: Double?,
raiseHandRating: Int64?, raiseHandRating: Int64?,
muteState: Participant.MuteState?, muteState: Participant.MuteState?,
isVideoMuted: Bool,
participationStatusChange: ParticipationStatusChange, participationStatusChange: ParticipationStatusChange,
volume: Int32?, volume: Int32?,
about: String?, about: String?,
@ -1162,12 +1172,12 @@ public final class GroupCallParticipantsContext {
) { ) {
self.peerId = peerId self.peerId = peerId
self.ssrc = ssrc self.ssrc = ssrc
self.jsonParams = jsonParams self.videoJsonDescription = videoJsonDescription
self.presentationJsonDescription = presentationJsonDescription
self.joinTimestamp = joinTimestamp self.joinTimestamp = joinTimestamp
self.activityTimestamp = activityTimestamp self.activityTimestamp = activityTimestamp
self.raiseHandRating = raiseHandRating self.raiseHandRating = raiseHandRating
self.muteState = muteState self.muteState = muteState
self.isVideoMuted = isVideoMuted
self.participationStatusChange = participationStatusChange self.participationStatusChange = participationStatusChange
self.volume = volume self.volume = volume
self.about = about self.about = about
@ -1182,7 +1192,7 @@ public final class GroupCallParticipantsContext {
} }
case state(update: StateUpdate) case state(update: StateUpdate)
case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted, title: String?, recordingStartTimestamp: Int32?, scheduleTimestamp: Int32?) case call(isTerminated: Bool, defaultParticipantsAreMuted: State.DefaultParticipantsAreMuted, title: String?, recordingStartTimestamp: Int32?, scheduleTimestamp: Int32?, isVideoEnabled: Bool)
} }
public final class MemberEvent { public final class MemberEvent {
@ -1376,6 +1386,7 @@ public final class GroupCallParticipantsContext {
scheduleTimestamp: strongSelf.stateValue.state.scheduleTimestamp, scheduleTimestamp: strongSelf.stateValue.state.scheduleTimestamp,
subscribedToScheduled: strongSelf.stateValue.state.subscribedToScheduled, subscribedToScheduled: strongSelf.stateValue.state.subscribedToScheduled,
totalCount: strongSelf.stateValue.state.totalCount, totalCount: strongSelf.stateValue.state.totalCount,
isVideoEnabled: strongSelf.stateValue.state.isVideoEnabled,
version: strongSelf.stateValue.state.version version: strongSelf.stateValue.state.version
), ),
overlayState: strongSelf.stateValue.overlayState overlayState: strongSelf.stateValue.overlayState
@ -1430,12 +1441,13 @@ public final class GroupCallParticipantsContext {
for update in updates { for update in updates {
if case let .state(update) = update { if case let .state(update) = update {
stateUpdates.append(update) stateUpdates.append(update)
} else if case let .call(_, defaultParticipantsAreMuted, title, recordingStartTimestamp, scheduleTimestamp) = update { } else if case let .call(_, defaultParticipantsAreMuted, title, recordingStartTimestamp, scheduleTimestamp, isVideoEnabled) = update {
var state = self.stateValue.state var state = self.stateValue.state
state.defaultParticipantsAreMuted = defaultParticipantsAreMuted state.defaultParticipantsAreMuted = defaultParticipantsAreMuted
state.recordingStartTimestamp = recordingStartTimestamp state.recordingStartTimestamp = recordingStartTimestamp
state.title = title state.title = title
state.scheduleTimestamp = scheduleTimestamp state.scheduleTimestamp = scheduleTimestamp
state.isVideoEnabled = isVideoEnabled
self.stateValue.state = state self.stateValue.state = state
} }
@ -1511,6 +1523,7 @@ public final class GroupCallParticipantsContext {
scheduleTimestamp: strongSelf.stateValue.state.scheduleTimestamp, scheduleTimestamp: strongSelf.stateValue.state.scheduleTimestamp,
subscribedToScheduled: strongSelf.stateValue.state.subscribedToScheduled, subscribedToScheduled: strongSelf.stateValue.state.subscribedToScheduled,
totalCount: strongSelf.stateValue.state.totalCount, totalCount: strongSelf.stateValue.state.totalCount,
isVideoEnabled: strongSelf.stateValue.state.isVideoEnabled,
version: strongSelf.stateValue.state.version version: strongSelf.stateValue.state.version
), ),
overlayState: strongSelf.stateValue.overlayState overlayState: strongSelf.stateValue.overlayState
@ -1698,14 +1711,14 @@ public final class GroupCallParticipantsContext {
let participant = Participant( let participant = Participant(
peer: peer, peer: peer,
ssrc: participantUpdate.ssrc, ssrc: participantUpdate.ssrc,
jsonParams: participantUpdate.jsonParams, videoJsonDescription: participantUpdate.videoJsonDescription,
presentationJsonDescription: participantUpdate.presentationJsonDescription,
joinTimestamp: previousJoinTimestamp ?? participantUpdate.joinTimestamp, joinTimestamp: previousJoinTimestamp ?? participantUpdate.joinTimestamp,
raiseHandRating: participantUpdate.raiseHandRating, raiseHandRating: participantUpdate.raiseHandRating,
hasRaiseHand: participantUpdate.raiseHandRating != nil, hasRaiseHand: participantUpdate.raiseHandRating != nil,
activityTimestamp: activityTimestamp, activityTimestamp: activityTimestamp,
activityRank: previousActivityRank, activityRank: previousActivityRank,
muteState: muteState, muteState: muteState,
isVideoMuted: participantUpdate.isVideoMuted,
volume: volume, volume: volume,
about: participantUpdate.about about: participantUpdate.about
) )
@ -1728,6 +1741,7 @@ public final class GroupCallParticipantsContext {
let title = strongSelf.stateValue.state.title let title = strongSelf.stateValue.state.title
let scheduleTimestamp = strongSelf.stateValue.state.scheduleTimestamp let scheduleTimestamp = strongSelf.stateValue.state.scheduleTimestamp
let subscribedToScheduled = strongSelf.stateValue.state.subscribedToScheduled let subscribedToScheduled = strongSelf.stateValue.state.subscribedToScheduled
let isVideoEnabled = strongSelf.stateValue.state.isVideoEnabled
updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) }) updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) })
@ -1744,6 +1758,7 @@ public final class GroupCallParticipantsContext {
scheduleTimestamp: scheduleTimestamp, scheduleTimestamp: scheduleTimestamp,
subscribedToScheduled: subscribedToScheduled, subscribedToScheduled: subscribedToScheduled,
totalCount: updatedTotalCount, totalCount: updatedTotalCount,
isVideoEnabled: isVideoEnabled,
version: update.version version: update.version
), ),
overlayState: updatedOverlayState overlayState: updatedOverlayState
@ -1783,7 +1798,7 @@ public final class GroupCallParticipantsContext {
})) }))
} }
public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?, isVideoMuted: Bool?, volume: Int32?, raiseHand: Bool?) { public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?, volume: Int32?, raiseHand: Bool?) {
if let current = self.stateValue.overlayState.pendingMuteStateChanges[peerId] { if let current = self.stateValue.overlayState.pendingMuteStateChanges[peerId] {
if current.state == muteState { if current.state == muteState {
return return
@ -1835,11 +1850,6 @@ public final class GroupCallParticipantsContext {
flags |= 1 << 0 flags |= 1 << 0
muted = .boolTrue muted = .boolTrue
} }
var videoMuted: Api.Bool?
if let isVideoMuted = isVideoMuted {
videoMuted = isVideoMuted ? .boolTrue : .boolFalse
flags |= 1 << 3
}
let raiseHandApi: Api.Bool? let raiseHandApi: Api.Bool?
if let raiseHand = raiseHand { if let raiseHand = raiseHand {
flags |= 1 << 2 flags |= 1 << 2
@ -1848,7 +1858,7 @@ public final class GroupCallParticipantsContext {
raiseHandApi = nil raiseHandApi = nil
} }
return account.network.request(Api.functions.phone.editGroupCallParticipant(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), participant: inputPeer, muted: muted, volume: volume, raiseHand: raiseHandApi, videoMuted: videoMuted)) return account.network.request(Api.functions.phone.editGroupCallParticipant(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), participant: inputPeer, muted: muted, volume: volume, raiseHand: raiseHandApi, videoMuted: nil))
|> map(Optional.init) |> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in |> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil) return .single(nil)
@ -1947,11 +1957,11 @@ public final class GroupCallParticipantsContext {
} }
public func raiseHand() { public func raiseHand() {
self.updateMuteState(peerId: self.myPeerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: true) self.updateMuteState(peerId: self.myPeerId, muteState: nil, volume: nil, raiseHand: true)
} }
public func lowerHand() { public func lowerHand() {
self.updateMuteState(peerId: self.myPeerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: false) self.updateMuteState(peerId: self.myPeerId, muteState: nil, volume: nil, raiseHand: false)
} }
public func updateShouldBeRecording(_ shouldBeRecording: Bool, title: String?) { public func updateShouldBeRecording(_ shouldBeRecording: Bool, title: String?) {
@ -2033,8 +2043,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, params): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, video, presentation):
//let params: Api.DataJSON? = nil
let peerId: PeerId = apiPeerId.peerId let peerId: PeerId = apiPeerId.peerId
let ssrc = UInt32(bitPattern: source) let ssrc = UInt32(bitPattern: source)
let muted = (flags & (1 << 0)) != 0 let muted = (flags & (1 << 0)) != 0
@ -2059,24 +2068,30 @@ extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
participationStatusChange = .none participationStatusChange = .none
} }
var jsonParams: String? = nil var videoJsonDescription: String? = nil
if let params = params { var presentationJsonDescription: String? = nil
switch params { if let video = video {
switch video {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data videoJsonDescription = data
}
}
if let presentation = presentation {
switch presentation {
case let .dataJSON(data):
presentationJsonDescription = data
} }
} }
let isVideoMuted = (flags & (1 << 14)) != 0
self.init( self.init(
peerId: peerId, peerId: peerId,
ssrc: ssrc, ssrc: ssrc,
jsonParams: jsonParams, videoJsonDescription: videoJsonDescription,
presentationJsonDescription: presentationJsonDescription,
joinTimestamp: date, joinTimestamp: date,
activityTimestamp: activeDate.flatMap(Double.init), activityTimestamp: activeDate.flatMap(Double.init),
raiseHandRating: raiseHandRating, raiseHandRating: raiseHandRating,
muteState: muteState, muteState: muteState,
isVideoMuted: isVideoMuted,
participationStatusChange: participationStatusChange, participationStatusChange: participationStatusChange,
volume: volume, volume: volume,
about: about, about: about,
@ -2091,8 +2106,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, params): case let .groupCallParticipant(flags, apiPeerId, date, activeDate, source, volume, about, raiseHandRating, video, presentation):
//let params: Api.DataJSON? = nil
let peerId: PeerId = apiPeerId.peerId let peerId: PeerId = apiPeerId.peerId
let ssrc = UInt32(bitPattern: source) let ssrc = UInt32(bitPattern: source)
let muted = (flags & (1 << 0)) != 0 let muted = (flags & (1 << 0)) != 0
@ -2117,24 +2131,30 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
participationStatusChange = .none participationStatusChange = .none
} }
var jsonParams: String? = nil var videoJsonDescription: String? = nil
if let params = params { var presentationJsonDescription: String? = nil
switch params { if let video = video {
switch video {
case let .dataJSON(data): case let .dataJSON(data):
jsonParams = data videoJsonDescription = data
}
}
if let presentation = presentation {
switch presentation {
case let .dataJSON(data):
presentationJsonDescription = data
} }
} }
let isVideoMuted = (flags & (1 << 14)) != 0
participantUpdates.append(GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate( participantUpdates.append(GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(
peerId: peerId, peerId: peerId,
ssrc: ssrc, ssrc: ssrc,
jsonParams: jsonParams, videoJsonDescription: videoJsonDescription,
presentationJsonDescription: presentationJsonDescription,
joinTimestamp: date, joinTimestamp: date,
activityTimestamp: activeDate.flatMap(Double.init), activityTimestamp: activeDate.flatMap(Double.init),
raiseHandRating: raiseHandRating, raiseHandRating: raiseHandRating,
muteState: muteState, muteState: muteState,
isVideoMuted: isVideoMuted,
participationStatusChange: participationStatusChange, participationStatusChange: participationStatusChange,
volume: volume, volume: volume,
about: about, about: about,

View File

@ -2991,13 +2991,14 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
}) })
switch call { switch call {
case let .groupCall(flags, _, _, _, _, title, _, recordStartDate, scheduleDate, _): case let .groupCall(flags, _, _, _, title, _, recordStartDate, scheduleDate, _):
let isMuted = (flags & (1 << 1)) != 0 let isMuted = (flags & (1 << 1)) != 0
let canChange = (flags & (1 << 2)) != 0 let canChange = (flags & (1 << 2)) != 0
let isVideoEnabled = (flags & (1 << 9)) != 0
let defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange) let defaultParticipantsAreMuted = GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: isMuted, canChange: canChange)
updatedGroupCallParticipants.append(( updatedGroupCallParticipants.append((
info.id, info.id,
.call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted, title: title, recordingStartTimestamp: recordStartDate, scheduleTimestamp: scheduleDate) .call(isTerminated: false, defaultParticipantsAreMuted: defaultParticipantsAreMuted, title: title, recordingStartTimestamp: recordStartDate, scheduleTimestamp: scheduleDate, isVideoEnabled: isVideoEnabled)
)) ))
default: default:
break break
@ -3006,7 +3007,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
case let .groupCallDiscarded(callId, _, _): case let .groupCallDiscarded(callId, _, _):
updatedGroupCallParticipants.append(( updatedGroupCallParticipants.append((
callId, callId,
.call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), title: nil, recordingStartTimestamp: nil, scheduleTimestamp: nil) .call(isTerminated: true, defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: false, canChange: false), title: nil, recordingStartTimestamp: nil, scheduleTimestamp: nil, isVideoEnabled: false)
)) ))
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in

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 128 return 129
} }
public func parseMessage(_ data: Data!) -> Any! { public func parseMessage(_ data: Data!) -> Any! {

View File

@ -287,10 +287,8 @@ public final class OngoingGroupCallContext {
deinit { deinit {
} }
func setJoinResponse(payload: String, participants: [(UInt32, String?)]) { func setJoinResponse(payload: String) {
self.context.setJoinResponsePayload(payload, participants: participants.map { participant -> OngoingGroupCallParticipantDescription in self.context.setJoinResponsePayload(payload)
return OngoingGroupCallParticipantDescription(audioSsrc: participant.0, jsonParams: participant.1)
})
} }
func addSsrcs(ssrcs: [UInt32]) { func addSsrcs(ssrcs: [UInt32]) {
@ -317,12 +315,12 @@ public final class OngoingGroupCallContext {
self.context.setFullSizeVideoSsrc(ssrc ?? 0) self.context.setFullSizeVideoSsrc(ssrc ?? 0)
} }
func addParticipants(participants: [(UInt32, String?)]) { func addParticipants(participants: [(UInt32, String?, String?)]) {
if participants.isEmpty { if participants.isEmpty {
return return
} }
self.context.addParticipants(participants.map { participant -> OngoingGroupCallParticipantDescription in self.context.addParticipants(participants.map { participant -> OngoingGroupCallParticipantDescription in
return OngoingGroupCallParticipantDescription(audioSsrc: participant.0, jsonParams: participant.1) return OngoingGroupCallParticipantDescription(audioSsrc: participant.0, videoJsonDescription: participant.1, screencastJsonDescription: participant.2)
}) })
} }
@ -596,9 +594,9 @@ public final class OngoingGroupCallContext {
impl.switchAudioOutput(deviceId) impl.switchAudioOutput(deviceId)
} }
} }
public func setJoinResponse(payload: String, participants: [(UInt32, String?)]) { public func setJoinResponse(payload: String) {
self.impl.with { impl in self.impl.with { impl in
impl.setJoinResponse(payload: payload, participants: participants) impl.setJoinResponse(payload: payload)
} }
} }
@ -632,7 +630,7 @@ public final class OngoingGroupCallContext {
} }
} }
public func addParticipants(participants: [(UInt32, String?)]) { public func addParticipants(participants: [(UInt32, String?, String?)]) {
self.impl.with { impl in self.impl.with { impl in
impl.addParticipants(participants: participants) impl.addParticipants(participants: participants)
} }

View File

@ -159,9 +159,10 @@ typedef struct {
@interface OngoingGroupCallParticipantDescription : NSObject @interface OngoingGroupCallParticipantDescription : NSObject
@property (nonatomic, readonly) uint32_t audioSsrc; @property (nonatomic, readonly) uint32_t audioSsrc;
@property (nonatomic, strong, readonly) NSString * _Nullable jsonParams; @property (nonatomic, strong, readonly) NSString * _Nullable videoJsonDescription;
@property (nonatomic, strong, readonly) NSString * _Nullable screencastJsonDescription;
- (instancetype _Nonnull)initWithAudioSsrc:(uint32_t)audioSsrc jsonParams:(NSString * _Nullable)jsonParams; - (instancetype _Nonnull)initWithAudioSsrc:(uint32_t)audioSsrc videoJsonDescription:(NSString * _Nullable)videoJsonDescription screencastJsonDescription:(NSString * _Nullable)screencastJsonDescription;
@end @end
@ -209,7 +210,7 @@ typedef NS_ENUM(int32_t, OngoingGroupCallVideoContentType) {
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled; - (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;
- (void)removeSsrcs:(NSArray<NSNumber *> * _Nonnull)ssrcs; - (void)removeSsrcs:(NSArray<NSNumber *> * _Nonnull)ssrcs;
- (void)removeIncomingVideoSource:(uint32_t)ssrc; - (void)removeIncomingVideoSource:(uint32_t)ssrc;
- (void)addParticipants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants; - (void)addParticipants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants;

View File

@ -433,7 +433,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
.enableNS = true, .enableNS = true,
.enableAGC = true, .enableAGC = true,
.enableCallUpgrade = false, .enableCallUpgrade = false,
.logPath = std::string(logPath.length == 0 ? "" : logPath.UTF8String), .logPath = std::string(logPath.length == 0 ? "" : logPath.UTF8String),
.statsLogPath = std::string(statsLogPath.length == 0 ? "" : statsLogPath.UTF8String), .statsLogPath = std::string(statsLogPath.length == 0 ? "" : statsLogPath.UTF8String),
.maxApiLayer = [OngoingCallThreadLocalContextWebrtc maxLayer], .maxApiLayer = [OngoingCallThreadLocalContextWebrtc maxLayer],
.enableHighBitrateVideo = true, .enableHighBitrateVideo = true,
@ -983,102 +983,6 @@ private:
} }
} }
static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonnull completion)(NSString * _Nonnull, uint32_t)) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
int32_t signedSsrc = *(int32_t *)&payload.ssrc;
dict[@"ssrc"] = @(signedSsrc);
dict[@"ufrag"] = [NSString stringWithUTF8String:payload.ufrag.c_str()];
dict[@"pwd"] = [NSString stringWithUTF8String:payload.pwd.c_str()];
NSMutableArray *fingerprints = [[NSMutableArray alloc] init];
for (auto &fingerprint : payload.fingerprints) {
[fingerprints addObject:@{
@"hash": [NSString stringWithUTF8String:fingerprint.hash.c_str()],
@"fingerprint": [NSString stringWithUTF8String:fingerprint.fingerprint.c_str()],
@"setup": [NSString stringWithUTF8String:fingerprint.setup.c_str()]
}];
}
dict[@"fingerprints"] = fingerprints;
NSMutableArray *parsedVideoSsrcGroups = [[NSMutableArray alloc] init];
NSMutableArray *parsedVideoSources = [[NSMutableArray alloc] init];
for (auto &group : payload.videoSourceGroups) {
NSMutableDictionary *parsedGroup = [[NSMutableDictionary alloc] init];
parsedGroup[@"semantics"] = [NSString stringWithUTF8String:group.semantics.c_str()];
NSMutableArray *sources = [[NSMutableArray alloc] init];
for (auto &source : group.ssrcs) {
[sources addObject:@(source)];
if (![parsedVideoSources containsObject:@(source)]) {
[parsedVideoSources addObject:@(source)];
}
}
parsedGroup[@"sources"] = sources;
[parsedVideoSsrcGroups addObject:parsedGroup];
}
if (parsedVideoSsrcGroups.count != 0) {
dict[@"ssrc-groups"] = parsedVideoSsrcGroups;
}
NSMutableArray *videoPayloadTypes = [[NSMutableArray alloc] init];
for (auto &payloadType : payload.videoPayloadTypes) {
NSMutableDictionary *parsedType = [[NSMutableDictionary alloc] init];
parsedType[@"id"] = @(payloadType.id);
NSString *name = [NSString stringWithUTF8String:payloadType.name.c_str()];
parsedType[@"name"] = name;
parsedType[@"clockrate"] = @(payloadType.clockrate);
if (![name isEqualToString:@"rtx"]) {
parsedType[@"channels"] = @(payloadType.channels);
}
NSMutableDictionary *parsedParameters = [[NSMutableDictionary alloc] init];
for (auto &it : payloadType.parameters) {
NSString *key = [NSString stringWithUTF8String:it.first.c_str()];
NSString *value = [NSString stringWithUTF8String:it.second.c_str()];
parsedParameters[key] = value;
}
if (parsedParameters.count != 0) {
parsedType[@"parameters"] = parsedParameters;
}
if (![name isEqualToString:@"rtx"]) {
NSMutableArray *parsedFbs = [[NSMutableArray alloc] init];
for (auto &it : payloadType.feedbackTypes) {
NSMutableDictionary *parsedFb = [[NSMutableDictionary alloc] init];
parsedFb[@"type"] = [NSString stringWithUTF8String:it.type.c_str()];
if (it.subtype.size() != 0) {
parsedFb[@"subtype"] = [NSString stringWithUTF8String:it.subtype.c_str()];
}
[parsedFbs addObject:parsedFb];
}
parsedType[@"rtcp-fbs"] = parsedFbs;
}
[videoPayloadTypes addObject:parsedType];
}
if (videoPayloadTypes.count != 0) {
dict[@"payload-types"] = videoPayloadTypes;
}
NSMutableArray *parsedExtensions = [[NSMutableArray alloc] init];
for (auto &it : payload.videoExtensionMap) {
NSMutableDictionary *parsedExtension = [[NSMutableDictionary alloc] init];
parsedExtension[@"id"] = @(it.first);
parsedExtension[@"uri"] = [NSString stringWithUTF8String:it.second.c_str()];
[parsedExtensions addObject:parsedExtension];
}
if (parsedExtensions.count != 0) {
dict[@"rtp-hdrexts"] = parsedExtensions;
}
NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
completion(string, payload.ssrc);
}
- (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled { - (void)setConnectionMode:(OngoingCallConnectionMode)connectionMode keepBroadcastConnectedIfWasEnabled:(bool)keepBroadcastConnectedIfWasEnabled {
if (_instance) { if (_instance) {
tgcalls::GroupConnectionMode mappedConnectionMode; tgcalls::GroupConnectionMode mappedConnectionMode;
@ -1106,184 +1010,15 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
- (void)emitJoinPayload:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion { - (void)emitJoinPayload:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion {
if (_instance) { if (_instance) {
_instance->emitJoinPayload([completion](tgcalls::GroupJoinPayload payload) { _instance->emitJoinPayload([completion](tgcalls::GroupJoinPayload const &payload) {
processJoinPayload(payload, completion); completion([NSString stringWithUTF8String:payload.json.c_str()], payload.audioSsrc);
}); });
} }
} }
- (void)setJoinResponsePayload:(NSString * _Nonnull)payload participants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants { - (void)setJoinResponsePayload:(NSString * _Nonnull)payload {
tgcalls::GroupJoinResponsePayload result;
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
if (payloadData == nil) {
return;
}
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:payloadData options:0 error:nil];
if (![dict isKindOfClass:[NSDictionary class]]) {
return;
}
NSDictionary *transport = dict[@"transport"];
if (![transport isKindOfClass:[NSDictionary class]]) {
return;
}
NSString *pwd = transport[@"pwd"];
if (![pwd isKindOfClass:[NSString class]]) {
return;
}
NSString *ufrag = transport[@"ufrag"];
if (![ufrag isKindOfClass:[NSString class]]) {
return;
}
result.pwd = [pwd UTF8String];
result.ufrag = [ufrag UTF8String];
NSArray *fingerprintsValue = transport[@"fingerprints"];
if (![fingerprintsValue isKindOfClass:[NSArray class]]) {
//return;
}
for (NSDictionary *fingerprintValue in fingerprintsValue) {
if (![fingerprintValue isKindOfClass:[NSDictionary class]]) {
continue;
}
NSString *hashValue = fingerprintValue[@"hash"];
if (![hashValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *fingerprint = fingerprintValue[@"fingerprint"];
if (![fingerprint isKindOfClass:[NSString class]]) {
continue;
}
NSString *setup = fingerprintValue[@"setup"];
if (![setup isKindOfClass:[NSString class]]) {
continue;
}
tgcalls::GroupJoinPayloadFingerprint parsed;
parsed.fingerprint = [fingerprint UTF8String];
parsed.setup = [setup UTF8String];
parsed.hash = [hashValue UTF8String];
result.fingerprints.push_back(parsed);
}
NSArray *candidatesValue = transport[@"candidates"];
if (![candidatesValue isKindOfClass:[NSArray class]]) {
return;
}
for (NSDictionary *candidateValue in candidatesValue) {
if (![candidateValue isKindOfClass:[NSDictionary class]]) {
continue;
}
NSString *portValue = candidateValue[@"port"];
if (![portValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *protocolValue = candidateValue[@"protocol"];
if (![protocolValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *networkValue = candidateValue[@"network"];
if (![networkValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *generationValue = candidateValue[@"generation"];
if (![generationValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *idValue = candidateValue[@"id"];
if (![idValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *componentValue = candidateValue[@"component"];
if (![componentValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *foundationValue = candidateValue[@"foundation"];
if (![foundationValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *priorityValue = candidateValue[@"priority"];
if (![priorityValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *ipValue = candidateValue[@"ip"];
if (![ipValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *typeValue = candidateValue[@"type"];
if (![typeValue isKindOfClass:[NSString class]]) {
continue;
}
NSString *tcpTypeValue = candidateValue[@"tcptype"];
if (![tcpTypeValue isKindOfClass:[NSString class]]) {
tcpTypeValue = @"";
}
NSString *relAddrValue = candidateValue[@"rel-addr"];
if (![relAddrValue isKindOfClass:[NSString class]]) {
relAddrValue = @"";
}
NSString *relPortValue = candidateValue[@"rel-port"];
if (![relPortValue isKindOfClass:[NSString class]]) {
relPortValue = @"";
}
tgcalls::GroupJoinResponseCandidate candidate;
candidate.port = [portValue UTF8String];
candidate.protocol = [protocolValue UTF8String];
candidate.network = [networkValue UTF8String];
candidate.generation = [generationValue UTF8String];
candidate.id = [idValue UTF8String];
candidate.component = [componentValue UTF8String];
candidate.foundation = [foundationValue UTF8String];
candidate.priority = [priorityValue UTF8String];
candidate.ip = [ipValue UTF8String];
candidate.type = [typeValue UTF8String];
candidate.tcpType = [tcpTypeValue UTF8String];
candidate.relAddr = [relAddrValue UTF8String];
candidate.relPort = [relPortValue UTF8String];
result.candidates.push_back(candidate);
}
std::vector<tgcalls::GroupParticipantDescription> parsedParticipants;
for (OngoingGroupCallParticipantDescription *participant in participants) {
tgcalls::GroupParticipantDescription parsedParticipant;
parsedParticipant.audioSsrc = participant.audioSsrc;
if (participant.jsonParams.length != 0) {
[self parseJsonIntoParticipant:participant.jsonParams participant: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(payload.UTF8String);
} }
} }
@ -1303,139 +1038,6 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
} }
} }
- (void)parseJsonIntoParticipant:(NSString *)payload participant:(tgcalls::GroupParticipantDescription &)participant {
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
if (payloadData == nil) {
return;
}
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:payloadData options:0 error:nil];
if (![dict isKindOfClass:[NSDictionary class]]) {
return;
}
NSString *endpointId = dict[@"endpoint"];
if (![endpointId isKindOfClass:[NSString class]]) {
return;
}
participant.endpointId = [endpointId UTF8String];
NSArray *ssrcGroups = dict[@"ssrc-groups"];
if ([ssrcGroups isKindOfClass:[NSArray class]]) {
for (NSDictionary *group in ssrcGroups) {
if (![group isKindOfClass:[NSDictionary class]]) {
continue;
}
NSString *semantics = group[@"semantics"];
if (![semantics isKindOfClass:[NSString class]]) {
continue;
}
NSArray *sources = group[@"sources"];
if (![sources isKindOfClass:[NSArray class]]) {
continue;
}
tgcalls::GroupJoinPayloadVideoSourceGroup groupDesc;
for (NSNumber *nSsrc in sources) {
if ([nSsrc isKindOfClass:[NSNumber class]]) {
groupDesc.ssrcs.push_back([nSsrc unsignedIntValue]);
}
}
groupDesc.semantics = [semantics UTF8String];
participant.videoSourceGroups.push_back(groupDesc);
}
}
NSArray *hdrExts = dict[@"rtp-hdrexts"];
if ([hdrExts isKindOfClass:[NSArray class]]) {
for (NSDictionary *extDict in hdrExts) {
if (![extDict isKindOfClass:[NSDictionary class]]) {
continue;
}
NSNumber *nId = extDict[@"id"];
if (![nId isKindOfClass:[NSNumber class]]) {
continue;
}
NSString *uri = extDict[@"uri"];
if (![uri isKindOfClass:[NSString class]]) {
continue;
}
participant.videoExtensionMap.push_back(std::make_pair((uint32_t)[nId unsignedIntValue], (std::string)[uri UTF8String]));
}
}
NSArray *payloadTypes = dict[@"payload-types"];
if ([payloadTypes isKindOfClass:[NSArray class]]) {
for (NSDictionary *payloadDict in payloadTypes) {
if (![payloadDict isKindOfClass:[NSDictionary class]]) {
continue;
}
NSNumber *nId = payloadDict[@"id"];
if (![nId isKindOfClass:[NSNumber class]]) {
continue;
}
NSNumber *nClockrate = payloadDict[@"clockrate"];
if (nClockrate != nil && ![nClockrate isKindOfClass:[NSNumber class]]) {
continue;
}
NSNumber *nChannels = payloadDict[@"channels"];
if (nChannels != nil && ![nChannels isKindOfClass:[NSNumber class]]) {
continue;
}
NSString *name = payloadDict[@"name"];
if (![name isKindOfClass:[NSString class]]) {
continue;
}
tgcalls::GroupJoinPayloadVideoPayloadType parsedPayload;
parsedPayload.id = [nId unsignedIntValue];
parsedPayload.clockrate = [nClockrate unsignedIntValue];
parsedPayload.channels = [nChannels unsignedIntValue];
parsedPayload.name = [name UTF8String];
NSArray *fbs = payloadDict[@"rtcp-fbs"];
if ([fbs isKindOfClass:[NSArray class]]) {
for (NSDictionary *fbDict in fbs) {
if (![fbDict isKindOfClass:[NSDictionary class]]) {
continue;
}
NSString *type = fbDict[@"type"];
if (![type isKindOfClass:[NSString class]]) {
continue;
}
NSString *subtype = fbDict[@"subtype"];
if (subtype != nil && ![subtype isKindOfClass:[NSString class]]) {
continue;
}
tgcalls::GroupJoinPayloadVideoPayloadFeedbackType parsedFeedback;
parsedFeedback.type = [type UTF8String];
if (subtype != nil) {
parsedFeedback.subtype = [subtype UTF8String];
}
parsedPayload.feedbackTypes.push_back(parsedFeedback);
}
}
NSDictionary *parameters = payloadDict[@"parameters"];
if ([parameters isKindOfClass:[NSDictionary class]]) {
for (NSString *nKey in parameters) {
if (![nKey isKindOfClass:[NSString class]]) {
continue;
}
NSString *value = parameters[nKey];
if (![value isKindOfClass:[NSString class]]) {
continue;
}
parsedPayload.parameters.push_back(std::make_pair((std::string)[nKey UTF8String], (std::string)[value UTF8String]));
}
}
participant.videoPayloadTypes.push_back(parsedPayload);
}
}
}
- (void)addParticipants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants { - (void)addParticipants:(NSArray<OngoingGroupCallParticipantDescription *> * _Nonnull)participants {
if (_instance) { if (_instance) {
std::vector<tgcalls::GroupParticipantDescription> parsedParticipants; std::vector<tgcalls::GroupParticipantDescription> parsedParticipants;
@ -1443,9 +1045,13 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
tgcalls::GroupParticipantDescription parsedParticipant; tgcalls::GroupParticipantDescription parsedParticipant;
parsedParticipant.audioSsrc = participant.audioSsrc; parsedParticipant.audioSsrc = participant.audioSsrc;
if (participant.jsonParams.length != 0) { if (participant.videoJsonDescription.length != 0) {
[self parseJsonIntoParticipant:participant.jsonParams participant:parsedParticipant]; parsedParticipant.videoInformation = participant.videoJsonDescription.UTF8String;
} }
if (participant.screencastJsonDescription.length != 0) {
parsedParticipant.screencastInformation = participant.screencastJsonDescription.UTF8String;
}
parsedParticipants.push_back(parsedParticipant); parsedParticipants.push_back(parsedParticipant);
} }
_instance->addParticipants(std::move(parsedParticipants)); _instance->addParticipants(std::move(parsedParticipants));
@ -1466,17 +1072,13 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
- (void)requestVideo:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer completion:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion { - (void)requestVideo:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer completion:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion {
if (_instance) { if (_instance) {
_instance->setVideoCapture([videoCapturer getInterface], [completion](auto payload){ _instance->setVideoCapture([videoCapturer getInterface]);
processJoinPayload(payload, completion);
});
} }
} }
- (void)disableVideo:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion { - (void)disableVideo:(void (^ _Nonnull)(NSString * _Nonnull, uint32_t))completion {
if (_instance) { if (_instance) {
_instance->setVideoCapture(nullptr, [completion](auto payload){ _instance->setVideoCapture(nullptr);
processJoinPayload(payload, completion);
});
} }
} }
@ -1548,11 +1150,12 @@ static void processJoinPayload(tgcalls::GroupJoinPayload &payload, void (^ _Nonn
@implementation OngoingGroupCallParticipantDescription @implementation OngoingGroupCallParticipantDescription
- (instancetype _Nonnull)initWithAudioSsrc:(uint32_t)audioSsrc jsonParams:(NSString * _Nullable)jsonParams { - (instancetype _Nonnull)initWithAudioSsrc:(uint32_t)audioSsrc videoJsonDescription:(NSString * _Nullable)videoJsonDescription screencastJsonDescription:(NSString * _Nullable)screencastJsonDescription {
self = [super init]; self = [super init];
if (self != nil) { if (self != nil) {
_audioSsrc = audioSsrc; _audioSsrc = audioSsrc;
_jsonParams = jsonParams; _videoJsonDescription = videoJsonDescription;
_screencastJsonDescription = screencastJsonDescription;
} }
return self; return self;
} }

@ -1 +1 @@
Subproject commit cd921e97bfc6af347ff7f938bd2f40e839f64f79 Subproject commit 00f592fd569246dca9bd10822b7d6291c2ce53e5