Immediately send updateGroupCallParticipant when is_muted changes.

This commit is contained in:
levlam 2021-02-12 15:41:20 +03:00
parent 1412e83363
commit ca64ad144a
4 changed files with 183 additions and 19 deletions

View File

@ -1365,7 +1365,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
auto *group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr && group_call->is_inited);
if (group_call->is_joined && group_call->is_active) {
auto can_self_unmute = !participant.server_is_muted_by_admin;
auto can_self_unmute = !participant.get_is_muted_by_admin();
if (can_self_unmute != group_call->can_self_unmute) {
group_call->can_self_unmute = can_self_unmute;
send_update_group_call(group_call, "process_group_call_participant");
@ -1841,11 +1841,73 @@ void GroupCallManager::toggle_group_call_participant_is_muted(GroupCallId group_
return promise.set_error(Status::Error(400, "Have no access to the user"));
}
if (user_id == td_->contacts_manager_->get_my_id() && !is_muted && !group_call->can_self_unmute) {
return promise.set_error(Status::Error(400, "Can't unmute self"));
auto participants = add_group_call_participants(input_group_call_id);
auto participant = get_group_call_participant(participants, user_id);
if (participant == nullptr) {
return promise.set_error(Status::Error(400, "Can't find group call participant"));
}
td_->create_handler<EditGroupCallMemberQuery>(std::move(promise))->send(input_group_call_id, user_id, is_muted, 0);
bool is_self = user_id == td_->contacts_manager_->get_my_id();
bool can_manage = can_manage_group_call(input_group_call_id);
bool is_admin = td::contains(participants->administrator_user_ids, user_id);
auto participant_copy = *participant;
if (!participant_copy.set_pending_is_muted(is_muted, can_manage, is_self, is_admin)) {
return promise.set_error(Status::Error(400, PSLICE() << "Can't " << (is_muted ? "" : "un") << "mute user"));
}
if (participant_copy == *participant) {
return promise.set_value(Unit());
}
*participant = std::move(participant_copy);
participant->pending_is_muted_generation = ++toggle_is_muted_generation_;
if (participant->order != 0) {
send_update_group_call_participant(input_group_call_id, *participant);
}
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, user_id,
generation = participant->pending_is_muted_generation,
promise = std::move(promise)](Result<Unit> &&result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
send_closure(actor_id, &GroupCallManager::on_toggle_group_call_participant_is_muted, input_group_call_id, user_id,
generation, std::move(promise));
}
});
td_->create_handler<EditGroupCallMemberQuery>(std::move(query_promise))
->send(input_group_call_id, user_id, is_muted, 0);
}
void GroupCallManager::on_toggle_group_call_participant_is_muted(InputGroupCallId input_group_call_id, UserId user_id,
uint64 generation, Promise<Unit> &&promise) {
if (G()->close_flag()) {
return promise.set_value(Unit());
}
auto *group_call = get_group_call(input_group_call_id);
if (group_call == nullptr || !group_call->is_inited || !group_call->is_active || !group_call->is_joined) {
return promise.set_value(Unit());
}
auto participant = get_group_call_participant(add_group_call_participants(input_group_call_id), user_id);
if (participant == nullptr || participant->pending_is_muted_generation != generation) {
return promise.set_value(Unit());
}
CHECK(participant->have_pending_is_muted);
if (participant->server_is_muted_by_themselves != participant->pending_is_muted_by_themselves ||
participant->server_is_muted_by_admin != participant->pending_is_muted_by_admin ||
participant->server_is_muted_locally != participant->pending_is_muted_locally) {
LOG(ERROR) << "Failed to mute/unmute " << user_id << " in " << input_group_call_id;
participant->have_pending_is_muted = false;
if (participant->order != 0) {
send_update_group_call_participant(input_group_call_id, *participant);
}
} else {
participant->have_pending_is_muted = false;
}
promise.set_value(Unit());
}
void GroupCallManager::set_group_call_participant_volume_level(GroupCallId group_call_id, UserId user_id,
@ -1912,6 +1974,7 @@ void GroupCallManager::on_set_group_call_participant_volume_level(InputGroupCall
return promise.set_value(Unit());
}
CHECK(participant->pending_volume_level != 0);
if (participant->volume_level != participant->pending_volume_level) {
LOG(ERROR) << "Failed to set volume level of " << user_id << " in " << input_group_call_id;
participant->pending_volume_level = 0;

View File

@ -174,6 +174,9 @@ class GroupCallManager : public Actor {
static GroupCallParticipant *get_group_call_participant(GroupCallParticipants *group_call_participants,
UserId user_id);
void on_toggle_group_call_participant_is_muted(InputGroupCallId input_group_call_id, UserId user_id,
uint64 generation, Promise<Unit> &&promise);
void on_set_group_call_participant_volume_level(InputGroupCallId input_group_call_id, UserId user_id,
uint64 generation, Promise<Unit> &&promise);
@ -243,6 +246,8 @@ class GroupCallManager : public Actor {
uint64 set_volume_level_generation_ = 0;
uint64 toggle_is_muted_generation_ = 0;
MultiTimeout check_group_call_is_joined_timeout_{"CheckGroupCallIsJoinedTimeout"};
MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"};
MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"};

View File

@ -46,8 +46,20 @@ bool GroupCallParticipant::is_versioned_update(const tl_object_ptr<telegram_api:
return participant->just_joined_ || participant->left_ || participant->versioned_;
}
bool GroupCallParticipant::get_is_muted() const {
return server_is_muted_by_themselves || server_is_muted_by_admin || server_is_muted_locally;
bool GroupCallParticipant::get_is_muted_by_themselves() const {
return have_pending_is_muted ? pending_is_muted_by_themselves : server_is_muted_by_themselves;
}
bool GroupCallParticipant::get_is_muted_by_admin() const {
return have_pending_is_muted ? pending_is_muted_by_admin : server_is_muted_by_admin;
}
bool GroupCallParticipant::get_is_muted_locally() const {
return have_pending_is_muted ? pending_is_muted_locally : server_is_muted_locally;
}
bool GroupCallParticipant::get_is_muted_for_all_users() const {
return get_is_muted_by_admin() || get_is_muted_by_themselves();
}
int32 GroupCallParticipant::get_volume_level() const {
@ -77,35 +89,45 @@ void GroupCallParticipant::update_from(const GroupCallParticipant &old_participa
pending_volume_level = old_participant.pending_volume_level;
pending_volume_level_generation = old_participant.pending_volume_level_generation;
have_pending_is_muted = old_participant.have_pending_is_muted;
pending_is_muted_by_themselves = old_participant.pending_is_muted_by_themselves;
pending_is_muted_by_admin = old_participant.pending_is_muted_by_admin;
pending_is_muted_locally = old_participant.pending_is_muted_locally;
pending_is_muted_generation = old_participant.pending_is_muted_generation;
}
bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bool is_admin) {
bool is_muted = get_is_muted();
bool is_muted_by_admin = server_is_muted_by_admin;
bool is_muted_by_themselves = server_is_muted_by_themselves;
bool is_muted_locally = server_is_muted_locally;
bool is_muted_by_admin = get_is_muted_by_admin();
bool is_muted_by_themselves = get_is_muted_by_themselves();
bool is_muted_locally = get_is_muted_locally();
CHECK(!is_muted_by_admin || !is_muted_by_themselves);
bool new_can_be_muted_for_all_users = false;
bool new_can_be_unmuted_for_all_users = false;
bool new_can_be_muted_only_for_self = !can_manage && !is_muted_locally;
bool new_can_be_unmuted_only_for_self = !can_manage && is_muted_locally;
if (is_self) {
// current user can be muted if !is_muted; after that is_muted_by_themselves
// current user can be muted if !is_muted_by_themselves && !is_muted_by_admin; after that is_muted_by_themselves
// current user can be unmuted if is_muted_by_themselves; after that !is_muted
new_can_be_muted_for_all_users = !is_muted;
new_can_be_muted_for_all_users = !is_muted_by_themselves && !is_muted_by_admin;
new_can_be_unmuted_for_all_users = is_muted_by_themselves;
new_can_be_muted_only_for_self = false;
new_can_be_unmuted_only_for_self = false;
} else if (is_admin) {
// admin user can be muted if can_manage && !is_muted; after that is_muted_by_themselves
// admin user can be muted if can_manage && !is_muted_by_themselves; after that is_muted_by_themselves
// admin user can't be unmuted
new_can_be_muted_for_all_users = can_manage && !is_muted;
new_can_be_muted_for_all_users = can_manage && !is_muted_by_themselves;
} else {
// other users can be muted if can_manage && !is_muted_by_admin; after that is_muted_by_admin
// other users can be unmuted if can_manage && is_muted_by_admin; after that is_muted_by_themselves
new_can_be_muted_for_all_users = can_manage && !is_muted_by_admin;
new_can_be_unmuted_for_all_users = can_manage && is_muted_by_admin;
}
CHECK(static_cast<int>(new_can_be_muted_for_all_users) + static_cast<int>(new_can_be_unmuted_for_all_users) +
static_cast<int>(new_can_be_muted_only_for_self) + static_cast<int>(new_can_be_unmuted_only_for_self) <=
1);
if (new_can_be_muted_for_all_users != can_be_muted_for_all_users ||
new_can_be_unmuted_for_all_users != can_be_unmuted_for_all_users ||
new_can_be_muted_only_for_self != can_be_muted_only_for_self ||
@ -119,6 +141,66 @@ bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bo
return false;
}
bool GroupCallParticipant::set_pending_is_muted(bool is_muted, bool can_manage, bool is_self, bool is_admin) {
update_can_be_muted(can_manage, is_self, is_admin);
if (is_muted) {
if (!can_be_muted_for_all_users && !can_be_muted_only_for_self) {
return false;
}
CHECK(!can_be_muted_for_all_users || !can_be_muted_only_for_self);
} else {
if (!can_be_unmuted_for_all_users && !can_be_unmuted_only_for_self) {
return false;
}
CHECK(!can_be_unmuted_for_all_users || !can_be_unmuted_only_for_self);
}
if (is_self) {
pending_is_muted_by_themselves = is_muted;
pending_is_muted_by_admin = false;
pending_is_muted_locally = false;
} else {
pending_is_muted_by_themselves = get_is_muted_by_themselves();
pending_is_muted_by_admin = get_is_muted_by_admin();
pending_is_muted_locally = get_is_muted_locally();
if (is_muted) {
if (can_be_muted_only_for_self) {
// local mute
pending_is_muted_locally = true;
} else {
// admin mute
CHECK(can_be_muted_for_all_users);
CHECK(can_manage);
if (is_admin) {
CHECK(!pending_is_muted_by_themselves);
pending_is_muted_by_admin = false;
pending_is_muted_by_themselves = true;
} else {
CHECK(!pending_is_muted_by_admin);
pending_is_muted_by_admin = true;
pending_is_muted_by_themselves = false;
}
}
} else {
if (can_be_unmuted_only_for_self) {
// local unmute
pending_is_muted_locally = false;
} else {
// admin unmute
CHECK(can_be_unmuted_for_all_users);
CHECK(can_manage);
CHECK(!is_admin);
pending_is_muted_by_admin = false;
pending_is_muted_by_themselves = true;
}
}
}
have_pending_is_muted = true;
update_can_be_muted(can_manage, is_self, is_admin);
return true;
}
td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group_call_participant_object(
ContactsManager *contacts_manager) const {
if (!is_valid()) {
@ -128,7 +210,7 @@ td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group
return td_api::make_object<td_api::groupCallParticipant>(
contacts_manager->get_user_id_object(user_id, "get_group_call_participant_object"), audio_source, is_speaking,
can_be_muted_for_all_users, can_be_unmuted_for_all_users, can_be_muted_only_for_self,
can_be_unmuted_only_for_self, server_is_muted_by_admin, server_is_muted_locally, server_is_muted_by_themselves,
can_be_unmuted_only_for_self, get_is_muted_for_all_users(), get_is_muted_locally(), get_is_muted_by_themselves(),
get_volume_level(), order);
}
@ -138,9 +220,9 @@ bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs
lhs.can_be_unmuted_for_all_users == rhs.can_be_unmuted_for_all_users &&
lhs.can_be_muted_only_for_self == rhs.can_be_muted_only_for_self &&
lhs.can_be_unmuted_only_for_self == rhs.can_be_unmuted_only_for_self &&
lhs.server_is_muted_by_admin == rhs.server_is_muted_by_admin &&
lhs.server_is_muted_locally == rhs.server_is_muted_locally &&
lhs.server_is_muted_by_themselves == rhs.server_is_muted_by_themselves && lhs.is_speaking == rhs.is_speaking &&
lhs.get_is_muted_for_all_users() == rhs.get_is_muted_for_all_users() &&
lhs.get_is_muted_locally() == rhs.get_is_muted_locally() &&
lhs.get_is_muted_by_themselves() == rhs.get_is_muted_by_themselves() && lhs.is_speaking == rhs.is_speaking &&
lhs.get_volume_level() == rhs.get_volume_level() && lhs.order == rhs.order;
}

View File

@ -43,6 +43,12 @@ struct GroupCallParticipant {
int32 pending_volume_level = 0;
uint64 pending_volume_level_generation = 0;
bool have_pending_is_muted = false;
bool pending_is_muted_by_themselves = false;
bool pending_is_muted_by_admin = false;
bool pending_is_muted_locally = false;
uint64 pending_is_muted_generation = 0;
static constexpr int32 MIN_VOLUME_LEVEL = 1;
static constexpr int32 MAX_VOLUME_LEVEL = 20000;
@ -56,6 +62,8 @@ struct GroupCallParticipant {
bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin);
bool set_pending_is_muted(bool is_muted, bool can_manage, bool is_self, bool is_admin);
int64 get_real_order() const {
return (static_cast<int64>(max(active_date, local_active_date)) << 32) + joined_date;
}
@ -64,7 +72,13 @@ struct GroupCallParticipant {
return user_id.is_valid();
}
bool get_is_muted() const;
bool get_is_muted_by_themselves() const;
bool get_is_muted_by_admin() const;
bool get_is_muted_locally() const;
bool get_is_muted_for_all_users() const;
int32 get_volume_level() const;