diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 8d7272faa5..a46b7eea56 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -660,3 +660,6 @@ groupCallSettingsAttentionButton: SettingsButton(groupCallSettingsButton) { groupCallBoxLabel: FlatLabel(boxLabel) { textFg: groupCallMembersFg; } + +groupCallRowBlobMinRadius: 26px; +groupCallRowBlobMaxRadius: 30px; diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index d03bdda74a..d59452582f 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -152,7 +152,7 @@ void GroupCall::join(const MTPInputGroupCall &inputCall) { }) | rpl::start_with_next([=](const Update &update) { Expects(update.was.has_value()); - _instance->removeSsrcs({ update.was->source }); + _instance->removeSsrcs({ update.was->ssrc }); }, _lifetime); } @@ -190,7 +190,7 @@ void GroupCall::rejoin() { root.insert("fingerprints", fingerprints); root.insert("ssrc", double(payload.ssrc)); - LOG(("Call Info: Join payload received, joining with source: %1." + LOG(("Call Info: Join payload received, joining with ssrc: %1." ).arg(ssrc)); const auto json = QJsonDocument(root).toJson( @@ -418,12 +418,12 @@ void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) { } if (data.is_left() && data.vsource().v == _mySsrc) { // I was removed from the call, rejoin. - LOG(("Call Info: Rejoin after got 'left' with my source.")); + LOG(("Call Info: Rejoin after got 'left' with my ssrc.")); setState(State::Joining); rejoin(); } else if (!data.is_left() && data.vsource().v != _mySsrc) { // I joined from another device, hangup. - LOG(("Call Info: Hangup after '!left' with source %1, my %2." + LOG(("Call Info: Hangup after '!left' with ssrc %1, my %2." ).arg(data.vsource().v ).arg(_mySsrc)); _mySsrc = 0; @@ -495,10 +495,10 @@ void GroupCall::handleLevelsUpdated( auto check = false; auto checkNow = false; const auto now = crl::now(); - for (const auto &[source, level] : data) { - const auto self = (source == _mySsrc); + for (const auto &[ssrc, level] : data) { + const auto self = (ssrc == _mySsrc); _levelUpdates.fire(LevelUpdate{ - .source = source, + .ssrc = ssrc, .value = level, .self = self }); @@ -515,9 +515,9 @@ void GroupCall::handleLevelsUpdated( } check = true; - const auto i = _lastSpoke.find(source); + const auto i = _lastSpoke.find(ssrc); if (i == _lastSpoke.end()) { - _lastSpoke.emplace(source, now); + _lastSpoke.emplace(ssrc, now); checkNow = true; } else { if (i->second + kCheckLastSpokeInterval / 3 <= now) { @@ -553,14 +553,14 @@ void GroupCall::checkLastSpoke() { const auto now = crl::now(); auto list = base::take(_lastSpoke); for (auto i = list.begin(); i != list.end();) { - const auto [source, when] = *i; + const auto [ssrc, when] = *i; if (when + kCheckLastSpokeInterval >= now) { hasRecent = true; ++i; } else { i = list.erase(i); } - real->applyLastSpoke(source, when, now); + real->applyLastSpoke(ssrc, when, now); } _lastSpoke = std::move(list); diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index b8c1f79883..52d1e7985c 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -28,7 +28,7 @@ enum class MuteState { }; struct LevelUpdate { - uint32 source = 0; + uint32 ssrc = 0; float value = 0.; bool self = false; }; diff --git a/Telegram/SourceFiles/calls/calls_group_members.cpp b/Telegram/SourceFiles/calls/calls_group_members.cpp index a584833e00..4125f4369d 100644 --- a/Telegram/SourceFiles/calls/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/calls_group_members.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_group_call.h" #include "data/data_peer_values.h" // Data::CanWriteValue. +#include "ui/paint/blobs.h" #include "ui/widgets/buttons.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/popup_menu.h" @@ -32,12 +33,37 @@ namespace Calls { namespace { constexpr auto kLevelThreshold = 0.2; +constexpr auto kRowBlobRadiusFactor = (float)(50. / 57.); +constexpr auto kLevelDuration = 100. + 500. * 0.33; +constexpr auto kScaleSmall = 0.704 - 0.1; +constexpr auto kScaleSmallMin = 0.926; +constexpr auto kScaleSmallMax = (float)(kScaleSmallMin + kScaleSmall); +constexpr auto kMaxLevel = 1.; -struct UpdateLevelResult { - bool levelChanged = false; - bool stateChanged = false; - crl::time nextUpdateTime = 0; -}; +auto RowBlobs() -> std::array { + return { { + { + .segmentsCount = 6, + .minScale = kScaleSmallMin / kScaleSmallMax, + .minRadius = st::groupCallRowBlobMinRadius + * kRowBlobRadiusFactor, + .maxRadius = st::groupCallRowBlobMaxRadius + * kRowBlobRadiusFactor, + .speedScale = 1., + .alpha = (76. / 255.), + }, + { + .segmentsCount = 8, + .minScale = kScaleSmallMin / kScaleSmallMax, + .minRadius = st::groupCallRowBlobMinRadius + * kRowBlobRadiusFactor, + .maxRadius = st::groupCallRowBlobMaxRadius + * kRowBlobRadiusFactor, + .speedScale = 1., + .alpha = (76. / 255.), + }, + } }; +} class Row final : public PeerListRow { public: @@ -50,10 +76,14 @@ public: }; void updateState(const Data::GroupCall::Participant *participant); - //UpdateLevelResult updateLevel(float level); + void updateLevel(float level); + void updateBlobAnimation(crl::time now); [[nodiscard]] State state() const { return _state; } + [[nodiscard]] uint32 ssrc() const { + return _ssrc; + } [[nodiscard]] bool speaking() const { return _speaking; } @@ -85,9 +115,12 @@ public: bool selected, bool actionSelected) override; + auto generatePaintUserpicCallback() -> PaintRoundImageCallback override; + private: void refreshStatus() override; void setSpeaking(bool speaking); + void setSsrc(uint32 ssrc); [[nodiscard]] static State ComputeState( not_null channel, @@ -98,10 +131,12 @@ private: State _state = State::Inactive; not_null _channel; not_null _st; - bool _speaking = false; - //float _level = 0.; - std::unique_ptr _actionRipple; + std::unique_ptr _blobs; + crl::time _blobsLastTime = 0; + uint32 _ssrc = 0; + float _level = 0.; + bool _speaking = false; }; @@ -132,9 +167,9 @@ public: -> rpl::producer>; private: - [[nodiscard]] std::unique_ptr createSelfRow() const; - [[nodiscard]] std::unique_ptr createRow( - const Data::GroupCall::Participant &participant) const; + [[nodiscard]] std::unique_ptr createSelfRow(); + [[nodiscard]] std::unique_ptr createRow( + const Data::GroupCall::Participant &participant); void prepareRows(not_null real); //void repaintByTimer(); @@ -146,9 +181,10 @@ private: const Data::GroupCall::Participant &now); void updateRow( not_null row, - const Data::GroupCall::Participant *participant) const; + const Data::GroupCall::Participant *participant); + void removeRow(not_null row); + void updateRowLevel(not_null row, float level); void checkSpeakingRowPosition(not_null row); - //void updateRowLevel(not_null user, float level); Row *findRow(not_null user) const; [[nodiscard]] Data::GroupCall *resolvedRealCall() const; @@ -167,8 +203,8 @@ private: not_null _menuParent; base::unique_qptr _menu; - //base::flat_map, crl::time> _repaintByTimer; - //base::Timer _repaintTimer; + base::flat_map> _speakingRowBySsrc; + Ui::Animations::Basic _speakingAnimation; rpl::lifetime _lifetime; @@ -183,6 +219,7 @@ Row::Row(not_null channel, not_null user) } void Row::updateState(const Data::GroupCall::Participant *participant) { + setSsrc(participant ? participant->ssrc : 0); if (!participant) { if (peer()->isSelf()) { setCustomStatus(tr::lng_group_call_connecting(tr::now)); @@ -193,7 +230,7 @@ void Row::updateState(const Data::GroupCall::Participant *participant) { setSpeaking(false); } else if (!participant->muted) { _state = State::Active; - setSpeaking(participant->speaking); + setSpeaking(participant->speaking && participant->ssrc != 0); } else if (participant->canSelfUnmute) { _state = State::Inactive; setSpeaking(false); @@ -209,42 +246,49 @@ void Row::setSpeaking(bool speaking) { return; } _speaking = speaking; + if (!_speaking) { + _blobs = nullptr; + } refreshStatus(); - //if (!_speaking) { - // updateLevel(0.); - //} } -//UpdateLevelResult Row::updateLevel(float level) { -// if (_level == level) { -// return UpdateLevelResult{ .nextUpdateTime = _markInactiveAt }; -// } -// const auto now = crl::now(); -// const auto stillActive = (now < _markInactiveAt); -// const auto wasActive = (_level >= kLevelThreshold) && stillActive; -// const auto nowActive = (level >= kLevelThreshold); -// if (nowActive) { -// _markInactiveAt = now + kLevelActiveTimeout; -// if (_state != State::Active) { -// _state = State::Active; -// _st = ComputeIconStyle(_state); -// } -// } -// _level = level; -// const auto changed = wasActive != (nowActive || stillActive); -// if (!changed) { -// return UpdateLevelResult{ -// .levelChanged = true, -// .nextUpdateTime = _markInactiveAt, -// }; -// } -// refreshStatus(now); -// return UpdateLevelResult{ -// .levelChanged = true, -// .stateChanged = true, -// .nextUpdateTime = _markInactiveAt, -// }; -//} +void Row::setSsrc(uint32 ssrc) { + _ssrc = ssrc; +} + +void Row::updateLevel(float level) { + Expects(_speaking); + + if (!_blobs) { + _blobs = std::make_unique( + RowBlobs() | ranges::to_vector, + kLevelDuration, + kMaxLevel); + _blobsLastTime = crl::now(); + } + _blobs->setLevel(level + 0.5); +} + +void Row::updateBlobAnimation(crl::time now) { + if (_blobs) { + _blobs->updateLevel(now - _blobsLastTime); + _blobsLastTime = now; + } +} + +auto Row::generatePaintUserpicCallback() -> PaintRoundImageCallback { + auto userpic = ensureUserpicView(); + return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { + if (_blobs) { + const auto shift = QPointF(x + size / 2., y + size / 2.); + p.translate(shift); + _blobs->paint(p, st::groupCallLive1); + p.translate(-shift); + p.setOpacity(1.); + } + peer()->paintUserpicLeft(p, userpic, x, y, outerWidth, size); + }; +} void Row::paintAction( Painter &p, @@ -333,8 +377,15 @@ MembersController::MembersController( : _call(call) , _channel(call->channel()) , _menuParent(menuParent) { -//, _repaintTimer([=] { repaintByTimer(); }) { setupListChangeViewers(call); + + _speakingAnimation.init([=](crl::time now) { + for (const auto [ssrc, row] : _speakingRowBySsrc) { + row->updateBlobAnimation(now); + delegate()->peerListUpdateRow(row); + } + return true; + }); } void MembersController::setupListChangeViewers(not_null call) { @@ -362,21 +413,13 @@ void MembersController::setupListChangeViewers(not_null call) { } }, _lifetime); - //call->levelUpdates( - //) | rpl::start_with_next([=](const LevelUpdate &update) { - // const auto findUserBySource = [&](uint32 source) -> UserData* { - // if (const auto real = resolvedRealCall()) { - // return real->userBySource(source); - // } - // return nullptr; - // }; - // const auto user = update.self - // ? _channel->session().user().get() - // : findUserBySource(update.source); - // if (user) { - // updateRowLevel(user, update.value); - // } - //}, _lifetime); + call->levelUpdates( + ) | rpl::start_with_next([=](const LevelUpdate &update) { + const auto i = _speakingRowBySsrc.find(update.ssrc); + if (i != end(_speakingRowBySsrc)) { + updateRowLevel(i->second, update.value); + } + }, _lifetime); } void MembersController::subscribeToChanges(not_null real) { @@ -402,10 +445,9 @@ void MembersController::subscribeToChanges(not_null real) { if (!update.now) { if (const auto row = findRow(user)) { if (user->isSelf()) { - row->updateState(nullptr); - delegate()->peerListUpdateRow(row); + updateRow(row, nullptr); } else { - delegate()->peerListRemoveRow(row); + removeRow(row); delegate()->peerListRefreshRows(); } } @@ -424,7 +466,7 @@ void MembersController::updateRow( } updateRow(row, &now); } else if (auto row = createRow(now)) { - if (now.speaking) { + if (row->speaking()) { delegate()->peerListPrependRow(std::move(row)); } else { delegate()->peerListAppendRow(std::move(row)); @@ -466,49 +508,49 @@ void MembersController::checkSpeakingRowPosition(not_null row) { void MembersController::updateRow( not_null row, - const Data::GroupCall::Participant *participant) const { + const Data::GroupCall::Participant *participant) { + const auto wasSpeaking = row->speaking(); + const auto wasSsrc = row->ssrc(); row->updateState(participant); + const auto nowSpeaking = row->speaking(); + const auto nowSsrc = row->ssrc(); + + const auto wasNoSpeaking = _speakingRowBySsrc.empty(); + if (wasSsrc == nowSsrc) { + if (nowSpeaking != wasSpeaking) { + if (nowSpeaking) { + _speakingRowBySsrc.emplace(nowSsrc, row); + } else { + _speakingRowBySsrc.remove(nowSsrc); + } + } + } else { + _speakingRowBySsrc.remove(wasSsrc); + if (nowSpeaking) { + Assert(nowSsrc != 0); + _speakingRowBySsrc.emplace(nowSsrc, row); + } + } + const auto nowNoSpeaking = _speakingRowBySsrc.empty(); + if (wasNoSpeaking && !nowNoSpeaking) { + _speakingAnimation.start(); + } else if (nowNoSpeaking && !wasNoSpeaking) { + _speakingAnimation.stop(); + } + delegate()->peerListUpdateRow(row); } -//void MembersController::updateRowLevel( -// not_null user, -// float level) { -// if (const auto row = findRow(user)) { -// const auto result = row->updateLevel(level); -// if (result.stateChanged) { -// delegate()->peerListUpdateRow(row); -// } -// if (result.nextUpdateTime) { -// _repaintByTimer[user] = result.nextUpdateTime; -// if (!_repaintTimer.isActive()) { -// _repaintTimer.callOnce(kLevelActiveTimeout); -// } -// } else if (_repaintByTimer.remove(user) && _repaintByTimer.empty()) { -// _repaintTimer.cancel(); -// } -// } -//} +void MembersController::removeRow(not_null row) { + _speakingRowBySsrc.remove(row->ssrc()); + delegate()->peerListRemoveRow(row); +} -//void MembersController::repaintByTimer() { -// const auto now = crl::now(); -// auto next = crl::time(0); -// for (auto i = begin(_repaintByTimer); i != end(_repaintByTimer);) { -// if (i->second > now) { -// if (!next || next > i->second) { -// next = i->second; -// } -// } else if (const auto row = findRow(i->first)) { -// delegate()->peerListUpdateRow(row); -// i = _repaintByTimer.erase(i); -// continue; -// } -// ++i; -// } -// if (next) { -// _repaintTimer.callOnce(next - now); -// } -//} +void MembersController::updateRowLevel( + not_null row, + float level) { + row->updateLevel(level); +} Row *MembersController::findRow(not_null user) const { return static_cast(delegate()->peerListFindRow(user->id)); @@ -564,7 +606,7 @@ void MembersController::prepareRows(not_null real) { ++i; } else { changed = true; - delegate()->peerListRemoveRow(row); + removeRow(static_cast(row.get())); --count; } } @@ -708,15 +750,15 @@ base::unique_qptr MembersController::rowContextMenu( return result; } -std::unique_ptr MembersController::createSelfRow() const { +std::unique_ptr MembersController::createSelfRow() { const auto self = _channel->session().user(); auto result = std::make_unique(_channel, self); updateRow(result.get(), nullptr); return result; } -std::unique_ptr MembersController::createRow( - const Data::GroupCall::Participant &participant) const { +std::unique_ptr MembersController::createRow( + const Data::GroupCall::Participant &participant) { auto result = std::make_unique(_channel, participant.user); updateRow(result.get(), &participant); return result; diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index 85d58eb32e..dde5a8d5bd 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -31,7 +31,7 @@ GroupCall::GroupCall( } GroupCall::~GroupCall() { - api().request(_unknownSourcesRequestId).cancel(); + api().request(_unknownSsrcsRequestId).cancel(); api().request(_participantsRequestId).cancel(); api().request(_reloadRequestId).cancel(); } @@ -65,7 +65,7 @@ void GroupCall::requestParticipants() { _participantsRequestId = api().request(MTPphone_GetGroupParticipants( input(), MTP_vector(), // ids - MTP_vector(), // sources + MTP_vector(), // ssrcs MTP_string(_nextOffset), MTP_int(kRequestPerPage) )).done([=](const MTPphone_GroupParticipants &result) { @@ -105,9 +105,9 @@ bool GroupCall::participantsLoaded() const { return _allReceived; } -UserData *GroupCall::userBySource(uint32 source) const { - const auto i = _userBySource.find(source); - return (i != end(_userBySource)) ? i->second.get() : nullptr; +UserData *GroupCall::userBySsrc(uint32 ssrc) const { + const auto i = _userBySsrc.find(ssrc); + return (i != end(_userBySsrc)) ? i->second.get() : nullptr; } rpl::producer<> GroupCall::participantsSliceAdded() { @@ -163,7 +163,7 @@ void GroupCall::reload() { result.match([&](const MTPDphone_groupCall &data) { _channel->owner().processUsers(data.vusers()); _participants.clear(); - _userBySource.clear(); + _userBySsrc.clear(); applyParticipantsSlice( data.vparticipants().v, ApplySliceSource::SliceLoaded); @@ -194,7 +194,7 @@ void GroupCall::applyParticipantsSlice( auto update = ParticipantUpdate{ .was = *i, }; - _userBySource.erase(i->source); + _userBySsrc.erase(i->ssrc); _participants.erase(i); if (sliceSource != ApplySliceSource::SliceLoaded) { _participantUpdates.fire(std::move(update)); @@ -212,20 +212,20 @@ void GroupCall::applyParticipantsSlice( .user = user, .date = data.vdate().v, .lastActive = was ? was->lastActive : 0, - .source = uint32(data.vsource().v), + .ssrc = uint32(data.vsource().v), .speaking = !data.is_muted() && (was ? was->speaking : false), .muted = data.is_muted(), .canSelfUnmute = !data.is_muted() || data.is_can_self_unmute(), }; if (i == end(_participants)) { - _userBySource.emplace(value.source, user); + _userBySsrc.emplace(value.ssrc, user); _participants.push_back(value); _channel->owner().unregisterInvitedToCallUser(_id, user); ++changedCount; } else { - if (i->source != value.source) { - _userBySource.erase(i->source); - _userBySource.emplace(value.source, user); + if (i->ssrc != value.ssrc) { + _userBySsrc.erase(i->ssrc); + _userBySsrc.emplace(value.ssrc, user); } *i = value; } @@ -271,11 +271,11 @@ void GroupCall::applyParticipantsMutes( } } -void GroupCall::applyLastSpoke(uint32 source, crl::time when, crl::time now) { - const auto i = _userBySource.find(source); - if (i == end(_userBySource)) { - _unknownSpokenSources.emplace(source, when); - requestUnknownSources(); +void GroupCall::applyLastSpoke(uint32 ssrc, crl::time when, crl::time now) { + const auto i = _userBySsrc.find(ssrc); + if (i == end(_userBySsrc)) { + _unknownSpokenSsrcs.emplace(ssrc, when); + requestUnknownSsrcs(); return; } const auto j = ranges::find(_participants, i->second, &Participant::user); @@ -292,32 +292,32 @@ void GroupCall::applyLastSpoke(uint32 source, crl::time when, crl::time now) { } } -void GroupCall::requestUnknownSources() { - if (_unknownSourcesRequestId || _unknownSpokenSources.empty()) { +void GroupCall::requestUnknownSsrcs() { + if (_unknownSsrcsRequestId || _unknownSpokenSsrcs.empty()) { return; } - const auto sources = [&] { - if (_unknownSpokenSources.size() < kRequestPerPage) { - return base::take(_unknownSpokenSources); + const auto ssrcs = [&] { + if (_unknownSpokenSsrcs.size() < kRequestPerPage) { + return base::take(_unknownSpokenSsrcs); } auto result = base::flat_map(); result.reserve(kRequestPerPage); while (result.size() < kRequestPerPage) { - const auto [source, when] = _unknownSpokenSources.back(); - result.emplace(source, when); - _unknownSpokenSources.erase(_unknownSpokenSources.end() - 1); + const auto [ssrc, when] = _unknownSpokenSsrcs.back(); + result.emplace(ssrc, when); + _unknownSpokenSsrcs.erase(_unknownSpokenSsrcs.end() - 1); } return result; }(); - auto sourceInputs = QVector(); - sourceInputs.reserve(sources.size()); - for (const auto [source, when] : sources) { - sourceInputs.push_back(MTP_int(source)); + auto inputs = QVector(); + inputs.reserve(ssrcs.size()); + for (const auto [ssrc, when] : ssrcs) { + inputs.push_back(MTP_int(ssrc)); } - _unknownSourcesRequestId = api().request(MTPphone_GetGroupParticipants( + _unknownSsrcsRequestId = api().request(MTPphone_GetGroupParticipants( input(), MTP_vector(), // ids - MTP_vector(sourceInputs), + MTP_vector(inputs), MTP_string(QString()), MTP_int(kRequestPerPage) )).done([=](const MTPphone_GroupParticipants &result) { @@ -327,19 +327,19 @@ void GroupCall::requestUnknownSources() { data.vparticipants().v, ApplySliceSource::UnknownLoaded); }); - _unknownSourcesRequestId = 0; + _unknownSsrcsRequestId = 0; const auto now = crl::now(); - for (const auto [source, when] : sources) { - applyLastSpoke(source, when, now); - _unknownSpokenSources.remove(source); + for (const auto [ssrc, when] : ssrcs) { + applyLastSpoke(ssrc, when, now); + _unknownSpokenSsrcs.remove(ssrc); } - requestUnknownSources(); + requestUnknownSsrcs(); }).fail([=](const RPCError &error) { - _unknownSourcesRequestId = 0; - for (const auto [source, when] : sources) { - _unknownSpokenSources.remove(source); + _unknownSsrcsRequestId = 0; + for (const auto [ssrc, when] : ssrcs) { + _unknownSpokenSsrcs.remove(ssrc); } - requestUnknownSources(); + requestUnknownSsrcs(); }).send(); } diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 2ee4b29019..7efb9f84f0 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -27,7 +27,7 @@ public: not_null user; TimeId date = 0; TimeId lastActive = 0; - uint32 source = 0; + uint32 ssrc = 0; bool speaking = false; bool muted = false; bool canSelfUnmute = false; @@ -41,7 +41,7 @@ public: -> const std::vector &; void requestParticipants(); [[nodiscard]] bool participantsLoaded() const; - [[nodiscard]] UserData *userBySource(uint32 source) const; + [[nodiscard]] UserData *userBySsrc(uint32 ssrc) const; [[nodiscard]] rpl::producer<> participantsSliceAdded(); [[nodiscard]] rpl::producer participantUpdated() const; @@ -50,7 +50,7 @@ public: void applyUpdate(const MTPDupdateGroupCallParticipants &update); void applyUpdateChecked( const MTPDupdateGroupCallParticipants &update); - void applyLastSpoke(uint32 source, crl::time when, crl::time now); + void applyLastSpoke(uint32 ssrc, crl::time when, crl::time now); [[nodiscard]] int fullCount() const; [[nodiscard]] rpl::producer fullCountValue() const; @@ -75,7 +75,7 @@ private: ApplySliceSource sliceSource); void applyParticipantsMutes( const MTPDupdateGroupCallParticipants &update); - void requestUnknownSources(); + void requestUnknownSsrcs(); const not_null _channel; const uint64 _id = 0; @@ -86,12 +86,12 @@ private: mtpRequestId _reloadRequestId = 0; std::vector _participants; - base::flat_map> _userBySource; + base::flat_map> _userBySsrc; QString _nextOffset; rpl::variable _fullCount = 0; - base::flat_map _unknownSpokenSources; - mtpRequestId _unknownSourcesRequestId = 0; + base::flat_map _unknownSpokenSsrcs; + mtpRequestId _unknownSsrcsRequestId = 0; rpl::event_stream _participantUpdates; rpl::event_stream<> _participantsSliceAdded;