Update API scheme to layer 129.

This commit is contained in:
John Preston 2021-04-29 13:56:09 +04:00
parent b3fcb4ef36
commit 69ceed5bbc
6 changed files with 159 additions and 105 deletions

View file

@ -375,6 +375,7 @@ updatePeerHistoryTTL#bb9bb9a5 flags:# peer:Peer ttl_period:flags.0?int = Update;
updateChatParticipant#f3b3781f flags:# chat_id:int date:int actor_id:int user_id:int prev_participant:flags.0?ChatParticipant new_participant:flags.1?ChatParticipant invite:flags.2?ExportedChatInvite qts:int = Update; updateChatParticipant#f3b3781f flags:# chat_id:int date:int actor_id:int user_id:int prev_participant:flags.0?ChatParticipant new_participant:flags.1?ChatParticipant invite:flags.2?ExportedChatInvite qts:int = Update;
updateChannelParticipant#7fecb1ec flags:# channel_id:int date:int actor_id:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant invite:flags.2?ExportedChatInvite qts:int = Update; updateChannelParticipant#7fecb1ec flags:# channel_id:int date:int actor_id:int user_id:int prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant invite:flags.2?ExportedChatInvite qts:int = Update;
updateBotStopped#7f9488a user_id:int date:int stopped:Bool qts:int = Update; updateBotStopped#7f9488a user_id:int date:int stopped:Bool qts:int = Update;
updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJSON = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -1204,11 +1205,11 @@ peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats; stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall; groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
groupCall#c95c6654 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true id:long access_hash:long participants_count:int params:flags.0?DataJSON title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int version:int = GroupCall; groupCall#653dbaad flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int version:int = GroupCall;
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall; inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
groupCallParticipant#b96b25ee flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true video_muted:flags.14?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long params:flags.6?DataJSON = GroupCallParticipant; groupCallParticipant#a8ba51a7 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long video:flags.6?DataJSON presentation:flags.14?DataJSON = GroupCallParticipant;
phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall; phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall;
@ -1624,7 +1625,7 @@ phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
phone.toggleGroupCallSettings#74bbb43d flags:# reset_invite_hash:flags.1?true call:InputGroupCall join_muted:flags.0?Bool = Updates; phone.toggleGroupCallSettings#74bbb43d flags:# reset_invite_hash:flags.1?true call:InputGroupCall join_muted:flags.0?Bool = Updates;
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall; phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector<InputPeer> sources:Vector<int> offset:string limit:int = phone.GroupParticipants; phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector<InputPeer> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool; phone.checkGroupCall#b59cf977 call:InputGroupCall sources:Vector<int> = Vector<int>;
phone.toggleGroupCallRecord#c02a66d7 flags:# start:flags.0?true call:InputGroupCall title:flags.1?string = Updates; phone.toggleGroupCallRecord#c02a66d7 flags:# start:flags.0?true call:InputGroupCall title:flags.1?string = Updates;
phone.editGroupCallParticipant#aec610e4 flags:# call:InputGroupCall participant:InputPeer muted:flags.0?Bool volume:flags.1?int raise_hand:flags.2?Bool video_muted:flags.3?Bool = Updates; phone.editGroupCallParticipant#aec610e4 flags:# call:InputGroupCall participant:InputPeer muted:flags.0?Bool volume:flags.1?int raise_hand:flags.2?Bool video_muted:flags.3?Bool = Updates;
phone.editGroupCallTitle#1ca6ac0a call:InputGroupCall title:string = Updates; phone.editGroupCallTitle#1ca6ac0a call:InputGroupCall title:string = Updates;
@ -1633,6 +1634,8 @@ phone.exportGroupCallInvite#e6aa647f flags:# can_self_unmute:flags.0?true call:I
phone.toggleGroupCallStartSubscription#219c34e6 call:InputGroupCall subscribed:Bool = Updates; phone.toggleGroupCallStartSubscription#219c34e6 call:InputGroupCall subscribed:Bool = Updates;
phone.startScheduledGroupCall#5680e342 call:InputGroupCall = Updates; phone.startScheduledGroupCall#5680e342 call:InputGroupCall = Updates;
phone.saveDefaultGroupCallJoinAs#575e1f8c peer:InputPeer join_as:InputPeer = Bool; phone.saveDefaultGroupCallJoinAs#575e1f8c peer:InputPeer join_as:InputPeer = Bool;
phone.joinGroupCallPresentation#cbea6bc4 call:InputGroupCall params:DataJSON = Updates;
phone.leaveGroupCallPresentation#1c50d144 call:InputGroupCall = Updates;
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference; langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>; langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
@ -1649,4 +1652,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats; stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
// LAYER 128 // LAYER 129

View file

@ -1878,6 +1878,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updatePhoneCall: case mtpc_updatePhoneCall:
case mtpc_updatePhoneCallSignalingData: case mtpc_updatePhoneCallSignalingData:
case mtpc_updateGroupCallParticipants: case mtpc_updateGroupCallParticipants:
case mtpc_updateGroupCallConnection:
case mtpc_updateGroupCall: { case mtpc_updateGroupCall: {
Core::App().calls().handleUpdate(&session(), update); Core::App().calls().handleUpdate(&session(), update);
} break; } break;

View file

@ -391,6 +391,8 @@ void Instance::handleUpdate(
handleSignalingData(session, data); handleSignalingData(session, data);
}, [&](const MTPDupdateGroupCall &data) { }, [&](const MTPDupdateGroupCall &data) {
handleGroupCallUpdate(session, update); handleGroupCallUpdate(session, update);
}, [&](const MTPDupdateGroupCallConnection &data) {
handleGroupCallUpdate(session, update);
}, [&](const MTPDupdateGroupCallParticipants &data) { }, [&](const MTPDupdateGroupCallParticipants &data) {
handleGroupCallUpdate(session, update); handleGroupCallUpdate(session, update);
}, [](const auto &) { }, [](const auto &) {
@ -482,10 +484,15 @@ void Instance::handleGroupCallUpdate(
&& (&_currentGroupCall->peer()->session() == session)) { && (&_currentGroupCall->peer()->session() == session)) {
update.match([&](const MTPDupdateGroupCall &data) { update.match([&](const MTPDupdateGroupCall &data) {
_currentGroupCall->handlePossibleCreateOrJoinResponse(data); _currentGroupCall->handlePossibleCreateOrJoinResponse(data);
}, [&](const MTPDupdateGroupCallConnection &data) {
_currentGroupCall->handlePossibleCreateOrJoinResponse(data);
}, [](const auto &) { }, [](const auto &) {
}); });
} }
if (update.type() == mtpc_updateGroupCallConnection) {
return;
}
const auto callId = update.match([](const MTPDupdateGroupCall &data) { const auto callId = update.match([](const MTPDupdateGroupCall &data) {
return data.vcall().match([](const auto &data) { return data.vcall().match([](const auto &data) {
return data.vid().v; return data.vid().v;

View file

@ -76,6 +76,12 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
return msgId / double(1ULL << 32); return msgId / double(1ULL << 32);
} }
[[nodiscard]] std::string ReadJsonString(
const QJsonObject &object,
const char *key) {
return object.value(key).toString().toStdString();
};
} // namespace } // namespace
struct VideoParams { struct VideoParams {
@ -177,13 +183,8 @@ std::shared_ptr<VideoParams> ParseVideoParams(
return data; return data;
} }
const auto readString = [](
const QJsonObject &object,
const char *key) {
return object.value(key).toString().toStdString();
};
const auto object = document.object(); const auto object = document.object();
data->description.endpointId = readString(object, "endpoint"); data->description.endpointId = ReadJsonString(object, "endpoint");
const auto ssrcGroups = object.value("ssrc-groups").toArray(); const auto ssrcGroups = object.value("ssrc-groups").toArray();
data->description.videoSourceGroups.reserve(ssrcGroups.size()); data->description.videoSourceGroups.reserve(ssrcGroups.size());
@ -201,58 +202,11 @@ std::shared_ptr<VideoParams> ParseVideoParams(
} }
data->description.videoSourceGroups.push_back({ data->description.videoSourceGroups.push_back({
.ssrcs = std::move(sources), .ssrcs = std::move(sources),
.semantics = readString(inner, "semantics"), .semantics = ReadJsonString(inner, "semantics"),
});
}
const auto payloadTypes = object.value("payload-types").toArray();
data->description.videoPayloadTypes.reserve(payloadTypes.size());
for (const auto &value : payloadTypes) {
const auto inner = value.toObject();
auto types = std::vector<GroupJoinPayloadVideoPayloadFeedbackType>();
{
const auto list = inner.value("rtcp-fbs").toArray();
types.reserve(list.size());
for (const auto &type : list) {
const auto inside = type.toObject();
types.push_back({
.type = readString(inside, "type"),
.subtype = readString(inside, "subtype"),
});
}
}
auto parameters = std::vector<std::pair<std::string, std::string>>();
{
const auto list = inner.value("parameters").toObject();
parameters.reserve(list.size());
for (auto i = list.begin(); i != list.end(); ++i) {
parameters.push_back({
i.key().toStdString(),
i.value().toString().toStdString(),
});
}
}
data->description.videoPayloadTypes.push_back({
.id = uint32_t(inner.value("id").toDouble()),
.name = readString(inner, "name"),
.clockrate = uint32_t(inner.value("clockrate").toDouble()),
.channels = uint32_t(inner.value("channels").toDouble()),
.feedbackTypes = std::move(types),
.parameters = std::move(parameters),
});
}
const auto extensionMap = object.value("rtp-hdrexts").toArray();
data->description.videoExtensionMap.reserve(extensionMap.size());
for (const auto &extension : extensionMap) {
const auto inner = extension.toObject();
data->description.videoExtensionMap.push_back({
uint32_t(inner.value("id").toDouble()),
readString(inner, "uri"),
}); });
} }
// videoPayloadTypes and videoExtensionMap will be in _commonVideoFields.
return data; return data;
} }
@ -950,7 +904,7 @@ void GroupCall::applyMeInCallLocally() {
| Flag::f_volume // Without flag the volume is reset to 100%. | Flag::f_volume // Without flag the volume is reset to 100%.
| Flag::f_volume_by_admin // Self volume can only be set by admin. | Flag::f_volume_by_admin // Self volume can only be set by admin.
| ((muted() != MuteState::Active) ? Flag::f_muted : Flag(0)) | ((muted() != MuteState::Active) ? Flag::f_muted : Flag(0))
| (videoMuted ? Flag::f_video_muted : Flag(0)) //| (videoMuted ? Flag(0) : Flag::f_video)
| (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0)); | (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0));
call->applyLocalUpdate( call->applyLocalUpdate(
MTP_updateGroupCallParticipants( MTP_updateGroupCallParticipants(
@ -966,7 +920,8 @@ void GroupCall::applyMeInCallLocally() {
MTP_int(volume), MTP_int(volume),
MTPstring(), // Don't update about text in local updates. MTPstring(), // Don't update about text in local updates.
MTP_long(raisedHandRating), MTP_long(raisedHandRating),
MTPDataJSON())), MTPDataJSON(), // video
MTPDataJSON())), // presentation
MTP_int(0)).c_updateGroupCallParticipants()); MTP_int(0)).c_updateGroupCallParticipants());
} }
@ -995,7 +950,7 @@ void GroupCall::applyParticipantLocally(
| (isMuted ? Flag::f_muted : Flag(0)) | (isMuted ? Flag::f_muted : Flag(0))
| (isMutedByYou ? Flag::f_muted_by_you : Flag(0)) | (isMutedByYou ? Flag::f_muted_by_you : Flag(0))
| (participantPeer == _joinAs ? Flag::f_self : Flag(0)) | (participantPeer == _joinAs ? Flag::f_self : Flag(0))
| (participant->videoMuted ? Flag::f_video_muted : Flag(0)) //| (participant->videoMuted ? Flag(0) : Flag::f_video)
| (participant->raisedHandRating | (participant->raisedHandRating
? Flag::f_raise_hand_rating ? Flag::f_raise_hand_rating
: Flag(0)); : Flag(0));
@ -1013,7 +968,8 @@ void GroupCall::applyParticipantLocally(
MTP_int(volume.value_or(participant->volume)), MTP_int(volume.value_or(participant->volume)),
MTPstring(), // Don't update about text in local updates. MTPstring(), // Don't update about text in local updates.
MTP_long(participant->raisedHandRating), MTP_long(participant->raisedHandRating),
MTPDataJSON())), MTPDataJSON(), // video
MTPDataJSON())), // presentation
MTP_int(0)).c_updateGroupCallParticipants()); MTP_int(0)).c_updateGroupCallParticipants());
} }
@ -1195,13 +1151,18 @@ void GroupCall::handlePossibleCreateOrJoinResponse(
} else if (_id != data.vid().v || !_instance) { } else if (_id != data.vid().v || !_instance) {
return; return;
} }
const auto streamDcId = MTP::BareDcId( if (const auto streamDcId = data.vstream_dc_id()) {
data.vstream_dc_id().value_or_empty()); _broadcastDcId = MTP::BareDcId(streamDcId->v);
const auto params = data.vparams(); }
if (!params) { }
void GroupCall::handlePossibleCreateOrJoinResponse(
const MTPDupdateGroupCallConnection &data) {
if (data.is_presentation()) {
// #TODO calls
return; return;
} }
params->match([&](const MTPDdataJSON &data) { data.vparams().match([&](const MTPDdataJSON &data) {
auto error = QJsonParseError{ 0, QJsonParseError::NoError }; auto error = QJsonParseError{ 0, QJsonParseError::NoError };
const auto document = QJsonDocument::fromJson( const auto document = QJsonDocument::fromJson(
data.vdata().v, data.vdata().v,
@ -1222,60 +1183,117 @@ void GroupCall::handlePossibleCreateOrJoinResponse(
}); });
if (document.object().value("stream").toBool()) { if (document.object().value("stream").toBool()) {
if (!streamDcId) { if (!_broadcastDcId) {
LOG(("Api Error: Empty stream_dc_id in groupCall.")); LOG(("Api Error: Empty stream_dc_id in groupCall."));
_broadcastDcId = _peer->session().mtp().mainDcId();
} }
_broadcastDcId = streamDcId
? streamDcId
: _peer->session().mtp().mainDcId();
setInstanceMode(InstanceMode::Stream); setInstanceMode(InstanceMode::Stream);
return; return;
} }
const auto readString = []( const auto readString = [](
const QJsonObject &object, const QJsonObject &object,
const char *key) { const char *key) {
return object.value(key).toString().toStdString(); return object.value(key).toString().toStdString();
}; };
const auto root = document.object().value("transport").toObject(); const auto root = document.object().value("transport").toObject();
const auto video = document.object().value("video").toObject();
auto payload = tgcalls::GroupJoinResponsePayload(); auto payload = tgcalls::GroupJoinResponsePayload();
payload.ufrag = readString(root, "ufrag"); payload.serverVideoBandwidthProbingSsrc = uint32_t(
payload.pwd = readString(root, "pwd"); video.value("server_sources").toArray().at(0).toDouble());
payload.ufrag = ReadJsonString(root, "ufrag");
payload.pwd = ReadJsonString(root, "pwd");
const auto prints = root.value("fingerprints").toArray(); const auto prints = root.value("fingerprints").toArray();
const auto candidates = root.value("candidates").toArray(); const auto candidates = root.value("candidates").toArray();
for (const auto &print : prints) { for (const auto &print : prints) {
const auto object = print.toObject(); const auto object = print.toObject();
payload.fingerprints.push_back({ payload.fingerprints.push_back({
.hash = readString(object, "hash"), .hash = ReadJsonString(object, "hash"),
.setup = readString(object, "setup"), .setup = ReadJsonString(object, "setup"),
.fingerprint = readString(object, "fingerprint"), .fingerprint = ReadJsonString(object, "fingerprint"),
}); });
} }
for (const auto &candidate : candidates) { for (const auto &candidate : candidates) {
const auto object = candidate.toObject(); const auto object = candidate.toObject();
payload.candidates.push_back({ payload.candidates.push_back({
.port = readString(object, "port"), .port = ReadJsonString(object, "port"),
.protocol = readString(object, "protocol"), .protocol = ReadJsonString(object, "protocol"),
.network = readString(object, "network"), .network = ReadJsonString(object, "network"),
.generation = readString(object, "generation"), .generation = ReadJsonString(object, "generation"),
.id = readString(object, "id"), .id = ReadJsonString(object, "id"),
.component = readString(object, "component"), .component = ReadJsonString(object, "component"),
.foundation = readString(object, "foundation"), .foundation = ReadJsonString(object, "foundation"),
.priority = readString(object, "priority"), .priority = ReadJsonString(object, "priority"),
.ip = readString(object, "ip"), .ip = ReadJsonString(object, "ip"),
.type = readString(object, "type"), .type = ReadJsonString(object, "type"),
.tcpType = readString(object, "tcpType"), .tcpType = ReadJsonString(object, "tcpType"),
.relAddr = readString(object, "relAddr"), .relAddr = ReadJsonString(object, "relAddr"),
.relPort = readString(object, "relPort"), .relPort = ReadJsonString(object, "relPort"),
}); });
} }
parseCommonVideoFields(video);
setInstanceMode(InstanceMode::Rtc); setInstanceMode(InstanceMode::Rtc);
_instance->setJoinResponsePayload(payload, {}); _instance->setJoinResponsePayload(payload, {});
addParticipantsToInstance();
}); });
} }
void GroupCall::parseCommonVideoFields(const QJsonObject &root) {
using namespace tgcalls;
_commonVideoFields = std::make_unique<GroupParticipantDescription>();
const auto raw = _commonVideoFields.get();
const auto payloadTypes = root.value("payload-types").toArray();
raw->videoPayloadTypes.reserve(payloadTypes.size());
for (const auto &value : payloadTypes) {
const auto inner = value.toObject();
auto types = std::vector<GroupJoinPayloadVideoPayloadFeedbackType>();
{
const auto list = inner.value("rtcp-fbs").toArray();
types.reserve(list.size());
for (const auto &type : list) {
const auto inside = type.toObject();
types.push_back({
.type = ReadJsonString(inside, "type"),
.subtype = ReadJsonString(inside, "subtype"),
});
}
}
auto parameters = std::vector<std::pair<std::string, std::string>>();
{
const auto list = inner.value("parameters").toObject();
parameters.reserve(list.size());
for (auto i = list.begin(); i != list.end(); ++i) {
parameters.push_back({
i.key().toStdString(),
i.value().toString().toStdString(),
});
}
}
raw->videoPayloadTypes.push_back({
.id = uint32_t(inner.value("id").toDouble()),
.name = ReadJsonString(inner, "name"),
.clockrate = uint32_t(inner.value("clockrate").toDouble()),
.channels = uint32_t(inner.value("channels").toDouble()),
.feedbackTypes = std::move(types),
.parameters = std::move(parameters),
});
}
const auto extensionMap = root.value("rtp-hdrexts").toArray();
raw->videoExtensionMap.reserve(extensionMap.size());
for (const auto &extension : extensionMap) {
const auto inner = extension.toObject();
raw->videoExtensionMap.push_back({
uint32_t(inner.value("id").toDouble()),
ReadJsonString(inner, "uri"),
});
}
}
void GroupCall::handlePossibleDiscarded(const MTPDgroupCallDiscarded &data) { void GroupCall::handlePossibleDiscarded(const MTPDgroupCallDiscarded &data) {
if (data.vid().v == _id) { if (data.vid().v == _id) {
LOG(("Call Info: Hangup after groupCallDiscarded.")); LOG(("Call Info: Hangup after groupCallDiscarded."));
@ -1286,7 +1304,9 @@ void GroupCall::handlePossibleDiscarded(const MTPDgroupCallDiscarded &data) {
void GroupCall::addParticipantsToInstance() { void GroupCall::addParticipantsToInstance() {
const auto real = lookupReal(); const auto real = lookupReal();
if (!real || (_instanceMode == InstanceMode::None)) { if (!real
|| (_instanceMode == InstanceMode::None)
|| (_instanceMode == InstanceMode::Rtc && !_commonVideoFields)) {
return; return;
} }
for (const auto &participant : real->participants()) { for (const auto &participant : real->participants()) {
@ -1297,10 +1317,15 @@ void GroupCall::addParticipantsToInstance() {
void GroupCall::prepareParticipantForAdding( void GroupCall::prepareParticipantForAdding(
const Data::GroupCallParticipant &participant) { const Data::GroupCallParticipant &participant) {
_preparedParticipants.push_back(participant.videoParams const auto withVideo = _commonVideoFields && participant.videoParams;
_preparedParticipants.push_back(withVideo
? participant.videoParams->description ? participant.videoParams->description
: tgcalls::GroupParticipantDescription()); : tgcalls::GroupParticipantDescription());
auto &added = _preparedParticipants.back(); auto &added = _preparedParticipants.back();
if (withVideo) {
added.videoSourceGroups = _commonVideoFields->videoSourceGroups;
added.videoExtensionMap = _commonVideoFields->videoExtensionMap;
}
added.audioSsrc = participant.ssrc; added.audioSsrc = participant.ssrc;
_unresolvedSsrcs.remove(added.audioSsrc); _unresolvedSsrcs.remove(added.audioSsrc);
for (const auto &group : added.videoSourceGroups) { for (const auto &group : added.videoSourceGroups) {
@ -1624,7 +1649,7 @@ void GroupCall::ensureControllerCreated() {
}); });
return result; return result;
}, },
.videoContentType = tgcalls::VideoContentType::Screencast, .videoContentType = tgcalls::VideoContentType::Generic,
}; };
if (Logs::DebugEnabled()) { if (Logs::DebugEnabled()) {
auto callLogFolder = cWorkingDir() + qsl("DebugLogs"); auto callLogFolder = cWorkingDir() + qsl("DebugLogs");
@ -1953,20 +1978,33 @@ void GroupCall::checkJoined() {
if (state() != State::Connecting || !_id || !_mySsrc) { if (state() != State::Connecting || !_id || !_mySsrc) {
return; return;
} }
auto sources = QVector<MTPint>(1, MTP_int(_mySsrc));
if (_screencastSsrc) {
sources.push_back(MTP_int(_screencastSsrc));
}
_api.request(MTPphone_CheckGroupCall( _api.request(MTPphone_CheckGroupCall(
inputCall(), inputCall(),
MTP_int(_mySsrc) MTP_vector<MTPint>(std::move(sources))
)).done([=](const MTPBool &result) { )).done([=](const MTPVector<MTPint> &result) {
if (!mtpIsTrue(result)) { if (!ranges::contains(result.v, MTP_int(_mySsrc))) {
LOG(("Call Info: Rejoin after FALSE in checkGroupCall.")); LOG(("Call Info: Rejoin after no _mySsrc in checkGroupCall."));
rejoin(); rejoin();
} else if (state() == State::Connecting) { } else if (state() == State::Connecting) {
_checkJoinedTimer.callOnce(kCheckJoinedTimeout); _checkJoinedTimer.callOnce(kCheckJoinedTimeout);
} }
if (_screencastSsrc
&& !ranges::contains(result.v, MTP_int(_screencastSsrc))) {
LOG(("Call Info: "
"Rejoin presentation after _screencastSsrc not found."));
// #TODO calls
}
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
LOG(("Call Info: Rejoin after error '%1' in checkGroupCall." LOG(("Call Info: Full rejoin after error '%1' in checkGroupCall."
).arg(error.type())); ).arg(error.type()));
rejoin(); rejoin();
if (_screencastSsrc) {
// #TODO calls
}
}).send(); }).send();
} }

View file

@ -143,6 +143,8 @@ public:
void join(const MTPInputGroupCall &inputCall); void join(const MTPInputGroupCall &inputCall);
void handleUpdate(const MTPUpdate &update); void handleUpdate(const MTPUpdate &update);
void handlePossibleCreateOrJoinResponse(const MTPDupdateGroupCall &data); void handlePossibleCreateOrJoinResponse(const MTPDupdateGroupCall &data);
void handlePossibleCreateOrJoinResponse(
const MTPDupdateGroupCallConnection &data);
void changeTitle(const QString &title); void changeTitle(const QString &title);
void toggleRecording(bool enabled, const QString &title); void toggleRecording(bool enabled, const QString &title);
[[nodiscard]] bool recordingStoppedByMe() const { [[nodiscard]] bool recordingStoppedByMe() const {
@ -299,6 +301,7 @@ private:
void handlePossibleDiscarded(const MTPDgroupCallDiscarded &data); void handlePossibleDiscarded(const MTPDgroupCallDiscarded &data);
void handleUpdate(const MTPDupdateGroupCall &data); void handleUpdate(const MTPDupdateGroupCall &data);
void handleUpdate(const MTPDupdateGroupCallParticipants &data); void handleUpdate(const MTPDupdateGroupCallParticipants &data);
void parseCommonVideoFields(const QJsonObject &root);
void ensureControllerCreated(); void ensureControllerCreated();
void destroyController(); void destroyController();
@ -391,6 +394,8 @@ private:
uint64 _id = 0; uint64 _id = 0;
uint64 _accessHash = 0; uint64 _accessHash = 0;
uint32 _mySsrc = 0; uint32 _mySsrc = 0;
uint32 _screencastSsrc = 0;
std::unique_ptr<tgcalls::GroupParticipantDescription> _commonVideoFields;
TimeId _scheduleDate = 0; TimeId _scheduleDate = 0;
base::flat_set<uint32> _mySsrcs; base::flat_set<uint32> _mySsrcs;
mtpRequestId _createRequestId = 0; mtpRequestId _createRequestId = 0;

View file

@ -549,8 +549,8 @@ void GroupCall::applyParticipantsSlice(
.peer = participantPeer, .peer = participantPeer,
.videoParams = (hasVideoParamsInformation .videoParams = (hasVideoParamsInformation
? Calls::ParseVideoParams( ? Calls::ParseVideoParams(
(data.vparams() (data.vvideo()
? data.vparams()->c_dataJSON().vdata().v ? data.vvideo()->c_dataJSON().vdata().v
: QByteArray()), : QByteArray()),
(i != end(_participants) (i != end(_participants)
? i->videoParams ? i->videoParams
@ -568,7 +568,7 @@ void GroupCall::applyParticipantsSlice(
.muted = data.is_muted(), .muted = data.is_muted(),
.mutedByMe = mutedByMe, .mutedByMe = mutedByMe,
.canSelfUnmute = canSelfUnmute, .canSelfUnmute = canSelfUnmute,
.videoMuted = data.is_video_muted(), .videoMuted = (data.vvideo() == nullptr),
.onlyMinLoaded = onlyMinLoaded, .onlyMinLoaded = onlyMinLoaded,
}; };
if (i == end(_participants)) { if (i == end(_participants)) {