From da5132b6886a82fece4ec3833db9b37563a34da7 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 6 Dec 2020 20:07:23 +0300 Subject: [PATCH] Send recent speaker updates with delay. --- td/telegram/GroupCallManager.cpp | 72 ++++++++++++++++++++++++++++---- td/telegram/GroupCallManager.h | 9 +++- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 06928109a..80c4d99aa 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -350,6 +350,8 @@ struct GroupCallManager::GroupCall { struct GroupCallManager::GroupCallRecentSpeakers { vector> users; // user + time; sorted by time + mutable bool is_changed = true; + mutable vector last_sent_user_ids; }; struct GroupCallManager::PendingJoinRequest { @@ -362,6 +364,9 @@ struct GroupCallManager::PendingJoinRequest { GroupCallManager::GroupCallManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { pending_send_speaking_action_timeout_.set_callback(on_pending_send_speaking_action_timeout_callback); pending_send_speaking_action_timeout_.set_callback_data(static_cast(this)); + + recent_speaker_update_timeout_.set_callback(on_recent_speaker_update_timeout_callback); + recent_speaker_update_timeout_.set_callback_data(static_cast(this)); } GroupCallManager::~GroupCallManager() = default; @@ -383,6 +388,10 @@ void GroupCallManager::on_pending_send_speaking_action_timeout_callback(void *gr } void GroupCallManager::on_send_speaking_action_timeout(GroupCallId group_call_id) { + if (G()->close_flag()) { + return; + } + LOG(INFO) << "Receive send_speaking_action timeout in " << group_call_id; auto input_group_call_id = get_input_group_call_id(group_call_id).move_as_ok(); @@ -400,6 +409,38 @@ void GroupCallManager::on_send_speaking_action_timeout(GroupCallId group_call_id DialogAction::get_speaking_action(), Promise()); } +void GroupCallManager::on_recent_speaker_update_timeout_callback(void *group_call_manager_ptr, + int64 group_call_id_int) { + if (G()->close_flag()) { + return; + } + + auto group_call_manager = static_cast(group_call_manager_ptr); + send_closure_later(group_call_manager->actor_id(group_call_manager), + &GroupCallManager::on_recent_speaker_update_timeout, + GroupCallId(narrow_cast(group_call_id_int))); +} + +void GroupCallManager::on_recent_speaker_update_timeout(GroupCallId group_call_id) { + if (G()->close_flag()) { + return; + } + + LOG(INFO) << "Receive recent speaker update timeout in " << group_call_id; + auto input_group_call_id = get_input_group_call_id(group_call_id).move_as_ok(); + + auto *group_call = get_group_call(input_group_call_id); + CHECK(group_call != nullptr && group_call->is_inited); + + auto &recent_speakers = group_call_recent_speakers_[group_call_id]; + CHECK(recent_speakers != nullptr); + if (!recent_speakers->is_changed) { + return; + } + + send_closure(G()->td(), &Td::send_update, get_update_group_call_object(group_call)); +} + GroupCallId GroupCallManager::get_group_call_id(InputGroupCallId input_group_call_id, ChannelId channel_id) { if (td_->auth_manager_->is_bot() || !input_group_call_id.is_valid()) { return GroupCallId(); @@ -969,7 +1010,7 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, is_updated = true; } if (is_updated) { - on_group_call_recent_speakers_updated(group_call); + on_group_call_recent_speakers_updated(group_call, recent_speakers.get()); } return; } @@ -987,18 +1028,23 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, recent_speakers->users.pop_back(); } - on_group_call_recent_speakers_updated(group_call); + on_group_call_recent_speakers_updated(group_call, recent_speakers.get()); } -void GroupCallManager::on_group_call_recent_speakers_updated(GroupCall *group_call) { - if (group_call == nullptr || !group_call->is_inited) { +void GroupCallManager::on_group_call_recent_speakers_updated(const GroupCall *group_call, + GroupCallRecentSpeakers *recent_speakers) { + if (group_call == nullptr || !group_call->is_inited || recent_speakers->is_changed) { return; } - send_closure(G()->td(), &Td::send_update, get_update_group_call_object(group_call)); + recent_speakers->is_changed = true; + + const double MAX_RECENT_SPEAKER_UPDATE_DELAY = 0.5; + recent_speaker_update_timeout_.set_timeout_in(group_call->group_call_id.get(), MAX_RECENT_SPEAKER_UPDATE_DELAY); } -tl_object_ptr GroupCallManager::get_group_call_object(const GroupCall *group_call) const { +tl_object_ptr GroupCallManager::get_group_call_object(const GroupCall *group_call, + bool for_update) const { CHECK(group_call != nullptr); CHECK(group_call->is_inited); @@ -1008,6 +1054,18 @@ tl_object_ptr GroupCallManager::get_group_call_object(const G for (auto &recent_speaker : recent_speakers_it->second->users) { recent_speaker_user_ids.push_back(recent_speaker.first.get()); } + + if (recent_speakers_it->second->is_changed) { + recent_speakers_it->second->is_changed = false; + + if (!for_update && recent_speakers_it->second->last_sent_user_ids != recent_speaker_user_ids) { + // the change must be received through update first + send_closure(G()->td(), &Td::send_update, get_update_group_call_object(group_call)); + } + } + if (recent_speakers_it->second->last_sent_user_ids != recent_speaker_user_ids) { + recent_speakers_it->second->last_sent_user_ids = recent_speaker_user_ids; + } } return td_api::make_object(group_call->group_call_id.get(), group_call->is_active, @@ -1018,7 +1076,7 @@ tl_object_ptr GroupCallManager::get_group_call_object(const G tl_object_ptr GroupCallManager::get_update_group_call_object( const GroupCall *group_call) const { - return td_api::make_object(get_group_call_object(group_call)); + return td_api::make_object(get_group_call_object(group_call, true)); } } // namespace td diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index 2cadfa7ff..e31a06929 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -77,6 +77,10 @@ class GroupCallManager : public Actor { void on_send_speaking_action_timeout(GroupCallId group_call_id); + static void on_recent_speaker_update_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int); + + void on_recent_speaker_update_timeout(GroupCallId group_call_id); + Result get_input_group_call_id(GroupCallId group_call_id); GroupCallId get_next_group_call_id(InputGroupCallId input_group_call_id); @@ -101,14 +105,14 @@ class GroupCallManager : public Actor { InputGroupCallId update_group_call(const tl_object_ptr &group_call_ptr, ChannelId channel_id); - void on_group_call_recent_speakers_updated(GroupCall *group_call); + void on_group_call_recent_speakers_updated(const GroupCall *group_call, GroupCallRecentSpeakers *recent_speakers); static Result> get_group_call_join_response_object( string json_response); tl_object_ptr get_update_group_call_object(const GroupCall *group_call) const; - tl_object_ptr get_group_call_object(const GroupCall *group_call) const; + tl_object_ptr get_group_call_object(const GroupCall *group_call, bool for_update = false) const; Td *td_; ActorShared<> parent_; @@ -128,6 +132,7 @@ class GroupCallManager : public Actor { uint64 join_group_request_generation_ = 0; MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"}; + MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"}; }; } // namespace td