1 /* 2 This file is part of Telegram Desktop, 3 the official desktop application for the Telegram messaging service. 4 5 For license and copyright information please follow this link: 6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 7 */ 8 #pragma once 9 10 #include "base/timer.h" 11 12 class PeerData; 13 14 class ApiWrap; 15 16 namespace Calls { 17 struct ParticipantVideoParams; 18 } // namespace Calls 19 20 namespace Data { 21 22 struct LastSpokeTimes { 23 crl::time anything = 0; 24 crl::time voice = 0; 25 }; 26 27 struct GroupCallParticipant { 28 not_null<PeerData*> peer; 29 std::shared_ptr<Calls::ParticipantVideoParams> videoParams; 30 TimeId date = 0; 31 TimeId lastActive = 0; 32 uint64 raisedHandRating = 0; 33 uint32 ssrc = 0; 34 int volume = 0; 35 bool sounding : 1; 36 bool speaking : 1; 37 bool additionalSounding : 1; 38 bool additionalSpeaking : 1; 39 bool muted : 1; 40 bool mutedByMe : 1; 41 bool canSelfUnmute : 1; 42 bool onlyMinLoaded : 1; 43 bool videoJoined = false; 44 bool applyVolumeFromMin = true; 45 46 [[nodiscard]] const std::string &cameraEndpoint() const; 47 [[nodiscard]] const std::string &screenEndpoint() const; 48 [[nodiscard]] bool cameraPaused() const; 49 [[nodiscard]] bool screenPaused() const; 50 }; 51 52 class GroupCall final { 53 public: 54 GroupCall( 55 not_null<PeerData*> peer, 56 CallId id, 57 CallId accessHash, 58 TimeId scheduleDate); 59 ~GroupCall(); 60 61 [[nodiscard]] CallId id() const; 62 [[nodiscard]] bool loaded() const; 63 [[nodiscard]] not_null<PeerData*> peer() const; 64 [[nodiscard]] MTPInputGroupCall input() const; title()65 [[nodiscard]] QString title() const { 66 return _title.current(); 67 } titleValue()68 [[nodiscard]] rpl::producer<QString> titleValue() const { 69 return _title.value(); 70 } setTitle(const QString & title)71 void setTitle(const QString &title) { 72 _title = title; 73 } recordStartDate()74 [[nodiscard]] TimeId recordStartDate() const { 75 return _recordStartDate.current(); 76 } recordStartDateValue()77 [[nodiscard]] rpl::producer<TimeId> recordStartDateValue() const { 78 return _recordStartDate.value(); 79 } recordStartDateChanges()80 [[nodiscard]] rpl::producer<TimeId> recordStartDateChanges() const { 81 return _recordStartDate.changes(); 82 } scheduleDate()83 [[nodiscard]] TimeId scheduleDate() const { 84 return _scheduleDate.current(); 85 } scheduleDateValue()86 [[nodiscard]] rpl::producer<TimeId> scheduleDateValue() const { 87 return _scheduleDate.value(); 88 } scheduleDateChanges()89 [[nodiscard]] rpl::producer<TimeId> scheduleDateChanges() const { 90 return _scheduleDate.changes(); 91 } scheduleStartSubscribed()92 [[nodiscard]] bool scheduleStartSubscribed() const { 93 return _scheduleStartSubscribed.current(); 94 } scheduleStartSubscribedValue()95 [[nodiscard]] rpl::producer<bool> scheduleStartSubscribedValue() const { 96 return _scheduleStartSubscribed.value(); 97 } unmutedVideoLimit()98 [[nodiscard]] int unmutedVideoLimit() const { 99 return _unmutedVideoLimit.current(); 100 } recordVideo()101 [[nodiscard]] bool recordVideo() const { 102 return _recordVideo.current(); 103 } 104 105 void setPeer(not_null<PeerData*> peer); 106 107 using Participant = GroupCallParticipant; 108 struct ParticipantUpdate { 109 std::optional<Participant> was; 110 std::optional<Participant> now; 111 }; 112 113 static constexpr auto kSoundStatusKeptFor = crl::time(1500); 114 115 [[nodiscard]] auto participants() const 116 -> const std::vector<Participant> &; 117 void requestParticipants(); 118 [[nodiscard]] bool participantsLoaded() const; 119 [[nodiscard]] PeerData *participantPeerByAudioSsrc(uint32 ssrc) const; 120 [[nodiscard]] const Participant *participantByPeer( 121 not_null<PeerData*> peer) const; 122 [[nodiscard]] const Participant *participantByEndpoint( 123 const std::string &endpoint) const; 124 125 [[nodiscard]] rpl::producer<> participantsReloaded(); 126 [[nodiscard]] auto participantUpdated() const 127 -> rpl::producer<ParticipantUpdate>; 128 [[nodiscard]] auto participantSpeaking() const 129 -> rpl::producer<not_null<Participant*>>; 130 131 void enqueueUpdate(const MTPUpdate &update); 132 void applyLocalUpdate( 133 const MTPDupdateGroupCallParticipants &update); 134 135 void applyLastSpoke(uint32 ssrc, LastSpokeTimes when, crl::time now); 136 void applyActiveUpdate( 137 PeerId participantPeerId, 138 LastSpokeTimes when, 139 PeerData *participantPeerLoaded); 140 141 void resolveParticipants(const base::flat_set<uint32> &ssrcs); 142 [[nodiscard]] rpl::producer< 143 not_null<const base::flat_map< 144 uint32, participantsResolved()145 LastSpokeTimes>*>> participantsResolved() const { 146 return _participantsResolved.events(); 147 } 148 149 [[nodiscard]] int fullCount() const; 150 [[nodiscard]] rpl::producer<int> fullCountValue() const; 151 152 void setInCall(); 153 void reload(); 154 void processFullCall(const MTPphone_GroupCall &call); 155 156 void setJoinMutedLocally(bool muted); 157 [[nodiscard]] bool joinMuted() const; 158 [[nodiscard]] bool canChangeJoinMuted() const; 159 [[nodiscard]] bool joinedToTop() const; 160 161 private: 162 enum class ApplySliceSource { 163 FullReloaded, 164 SliceLoaded, 165 UnknownLoaded, 166 UpdateReceived, 167 UpdateConstructed, 168 }; 169 enum class QueuedType : uint8 { 170 VersionedParticipant, 171 Participant, 172 Call, 173 }; 174 [[nodiscard]] ApiWrap &api() const; 175 176 void discard(const MTPDgroupCallDiscarded &data); 177 [[nodiscard]] bool inCall() const; 178 void applyParticipantsSlice( 179 const QVector<MTPGroupCallParticipant> &list, 180 ApplySliceSource sliceSource); 181 void requestUnknownParticipants(); 182 void changePeerEmptyCallFlag(); 183 void checkFinishSpeakingByActive(); 184 void applyCallFields(const MTPDgroupCall &data); 185 void applyEnqueuedUpdate(const MTPUpdate &update); 186 void setServerParticipantsCount(int count); 187 void computeParticipantsCount(); 188 void processQueuedUpdates(); 189 void processFullCallUsersChats(const MTPphone_GroupCall &call); 190 void processFullCallFields(const MTPphone_GroupCall &call); 191 [[nodiscard]] bool requestParticipantsAfterReload( 192 const MTPphone_GroupCall &call) const; 193 [[nodiscard]] bool processSavedFullCall(); 194 void finishParticipantsSliceRequest(); 195 [[nodiscard]] Participant *findParticipant(not_null<PeerData*> peer); 196 197 const CallId _id = 0; 198 const CallId _accessHash = 0; 199 200 not_null<PeerData*> _peer; 201 int _version = 0; 202 mtpRequestId _participantsRequestId = 0; 203 mtpRequestId _reloadRequestId = 0; 204 rpl::variable<QString> _title; 205 206 base::flat_multi_map< 207 std::pair<int, QueuedType>, 208 MTPUpdate> _queuedUpdates; 209 base::Timer _reloadByQueuedUpdatesTimer; 210 std::optional<MTPphone_GroupCall> _savedFull; 211 212 std::vector<Participant> _participants; 213 base::flat_map<uint32, not_null<PeerData*>> _participantPeerByAudioSsrc; 214 base::flat_map<not_null<PeerData*>, crl::time> _speakingByActiveFinishes; 215 base::Timer _speakingByActiveFinishTimer; 216 QString _nextOffset; 217 int _serverParticipantsCount = 0; 218 rpl::variable<int> _fullCount = 0; 219 rpl::variable<int> _unmutedVideoLimit = 0; 220 rpl::variable<bool> _recordVideo = 0; 221 rpl::variable<TimeId> _recordStartDate = 0; 222 rpl::variable<TimeId> _scheduleDate = 0; 223 rpl::variable<bool> _scheduleStartSubscribed = false; 224 225 base::flat_map<uint32, LastSpokeTimes> _unknownSpokenSsrcs; 226 base::flat_map<PeerId, LastSpokeTimes> _unknownSpokenPeerIds; 227 rpl::event_stream< 228 not_null<const base::flat_map< 229 uint32, 230 LastSpokeTimes>*>> _participantsResolved; 231 mtpRequestId _unknownParticipantPeersRequestId = 0; 232 233 rpl::event_stream<ParticipantUpdate> _participantUpdates; 234 rpl::event_stream<not_null<Participant*>> _participantSpeaking; 235 rpl::event_stream<> _participantsReloaded; 236 237 bool _joinMuted = false; 238 bool _canChangeJoinMuted = true; 239 bool _allParticipantsLoaded = false; 240 bool _joinedToTop = false; 241 bool _applyingQueuedUpdates = false; 242 243 }; 244 245 } // namespace Data 246