Add startGroupCallScreenSharing.

This commit is contained in:
levlam 2021-04-30 19:53:39 +03:00
parent 2061210089
commit 2225e56906
8 changed files with 189 additions and 18 deletions

View File

@ -4612,15 +4612,18 @@ startScheduledGroupCall group_call_id:int32 = Ok;
//@group_call_id Group call identifier @enabled_start_notification New value of the enabled_start_notification setting //@group_call_id Group call identifier @enabled_start_notification New value of the enabled_start_notification setting
toggleGroupCallEnabledStartNotification group_call_id:int32 enabled_start_notification:Bool = Ok; toggleGroupCallEnabledStartNotification group_call_id:int32 enabled_start_notification:Bool = Ok;
//@description Joins an active group call //@description Joins an active group call. Returns join response payload for tgcalls
//@group_call_id Group call identifier //@group_call_id Group call identifier
//@participant_id Identifier of a group call participant, which will be used to join the call; voice chats only //@participant_id Identifier of a group call participant, which will be used to join the call; voice chats only
//@audio_source Caller audio synchronization source identifier; received from tgcalls //@audio_source Caller audio synchronization source identifier; received from tgcalls
//@payload Group join payload; received from tgcalls //@payload Group call join payload; received from tgcalls
//@is_muted True, if the user's microphone is muted //@is_muted True, if the user's microphone is muted
//@invite_hash If non-empty, invite hash to be used to join the group call without being muted by administrators //@invite_hash If non-empty, invite hash to be used to join the group call without being muted by administrators
joinGroupCall group_call_id:int32 participant_id:MessageSender audio_source:int32 payload:string is_muted:Bool invite_hash:string = Text; joinGroupCall group_call_id:int32 participant_id:MessageSender audio_source:int32 payload:string is_muted:Bool invite_hash:string = Text;
//@description Starts screen sharing in a joined group call. Returns join response payload for tgcalls @group_call_id Group call identifier @payload Group call join payload; received from tgcalls
startGroupCallScreenSharing group_call_id:int32 payload:string = Text;
//@description Sets group call title. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier @title New group call title; 1-64 characters //@description Sets group call title. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier @title New group call title; 1-64 characters
setGroupCallTitle group_call_id:int32 title:string = Ok; setGroupCallTitle group_call_id:int32 title:string = Ok;

View File

@ -404,6 +404,41 @@ class JoinGroupCallQuery : public Td::ResultHandler {
} }
}; };
class JoinGroupCallPresentationQuery : public Td::ResultHandler {
InputGroupCallId input_group_call_id_;
uint64 generation_ = 0;
public:
NetQueryRef send(InputGroupCallId input_group_call_id, const string &payload, uint64 generation) {
input_group_call_id_ = input_group_call_id;
generation_ = generation;
auto query = G()->net_query_creator().create(telegram_api::phone_joinGroupCallPresentation(
input_group_call_id.get_input_group_call(), make_tl_object<telegram_api::dataJSON>(payload)));
auto join_query_ref = query.get_weak();
send_query(std::move(query));
return join_query_ref;
}
void on_result(uint64 id, BufferSlice packet) override {
auto result_ptr = fetch_result<telegram_api::phone_joinGroupCallPresentation>(packet);
if (result_ptr.is_error()) {
return on_error(id, result_ptr.move_as_error());
}
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for JoinGroupCallPresentationQuery with generation " << generation_ << ": "
<< to_string(ptr);
td->group_call_manager_->process_join_group_call_presentation_response(input_group_call_id_, generation_,
std::move(ptr), Status::OK());
}
void on_error(uint64 id, Status status) override {
td->group_call_manager_->process_join_group_call_presentation_response(input_group_call_id_, generation_, nullptr,
std::move(status));
}
};
class EditGroupCallTitleQuery : public Td::ResultHandler { class EditGroupCallTitleQuery : public Td::ResultHandler {
Promise<Unit> promise_; Promise<Unit> promise_;
@ -2170,6 +2205,22 @@ int32 GroupCallManager::cancel_join_group_call_request(InputGroupCallId input_gr
return audio_source; return audio_source;
} }
int32 GroupCallManager::cancel_join_group_call_presentation_request(InputGroupCallId input_group_call_id) {
auto it = pending_join_presentation_requests_.find(input_group_call_id);
if (it == pending_join_presentation_requests_.end()) {
return 0;
}
CHECK(it->second != nullptr);
if (!it->second->query_ref.empty()) {
cancel_query(it->second->query_ref);
}
it->second->promise.set_error(Status::Error(200, "Cancelled"));
auto audio_source = it->second->audio_source;
pending_join_presentation_requests_.erase(it);
return audio_source;
}
void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, int64 time_offset, int32 scale, void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, int64 time_offset, int32 scale,
Promise<string> &&promise) { Promise<string> &&promise) {
if (G()->close_flag()) { if (G()->close_flag()) {
@ -2279,7 +2330,7 @@ void GroupCallManager::start_scheduled_group_call(GroupCallId group_call_id, Pro
} }
void GroupCallManager::join_group_call(GroupCallId group_call_id, DialogId as_dialog_id, int32 audio_source, void GroupCallManager::join_group_call(GroupCallId group_call_id, DialogId as_dialog_id, int32 audio_source,
const string &payload, bool is_muted, const string &invite_hash, string &&payload, bool is_muted, const string &invite_hash,
Promise<string> &&promise) { Promise<string> &&promise) {
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
@ -2382,6 +2433,49 @@ void GroupCallManager::join_group_call(GroupCallId group_call_id, DialogId as_di
try_load_group_call_administrators(input_group_call_id, group_call->dialog_id); try_load_group_call_administrators(input_group_call_id, group_call->dialog_id);
} }
void GroupCallManager::start_group_call_screen_sharing(GroupCallId group_call_id, string &&payload,
Promise<string> &&promise) {
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
auto *group_call = get_group_call(input_group_call_id);
CHECK(group_call != nullptr);
if (!group_call->is_inited || !group_call->is_active) {
return promise.set_error(Status::Error(400, "GROUPCALL_JOIN_MISSING"));
}
if (!group_call->is_joined || group_call->is_being_left) {
if (is_group_call_being_joined(input_group_call_id) || group_call->need_rejoin) {
group_call->after_join.push_back(
PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, payload = std::move(payload),
promise = std::move(promise)](Result<Unit> &&result) mutable {
if (result.is_error()) {
promise.set_error(Status::Error(400, "GROUPCALL_JOIN_MISSING"));
} else {
send_closure(actor_id, &GroupCallManager::start_group_call_screen_sharing, group_call_id,
std::move(payload), std::move(promise));
}
}));
return;
}
return promise.set_error(Status::Error(400, "GROUPCALL_JOIN_MISSING"));
}
cancel_join_group_call_presentation_request(input_group_call_id);
auto generation = ++join_group_request_generation_;
auto &request = pending_join_presentation_requests_[input_group_call_id];
request = make_unique<PendingJoinRequest>();
request->generation = generation;
request->promise = std::move(promise);
request->query_ref =
td_->create_handler<JoinGroupCallPresentationQuery>()->send(input_group_call_id, payload, generation);
bool need_update = false;
if (group_call->is_inited && need_update) {
send_update_group_call(group_call, "start_group_call_screen_sharing");
}
}
void GroupCallManager::try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id) { void GroupCallManager::try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id) {
if (!dialog_id.is_valid() || !need_group_call_participants(input_group_call_id) || if (!dialog_id.is_valid() || !need_group_call_participants(input_group_call_id) ||
can_manage_group_calls(dialog_id).is_error()) { can_manage_group_calls(dialog_id).is_error()) {
@ -2455,6 +2549,29 @@ void GroupCallManager::process_join_group_call_response(InputGroupCallId input_g
})); }));
} }
void GroupCallManager::process_join_group_call_presentation_response(InputGroupCallId input_group_call_id,
uint64 generation,
tl_object_ptr<telegram_api::Updates> &&updates,
Status status) {
auto it = pending_join_presentation_requests_.find(input_group_call_id);
if (it == pending_join_presentation_requests_.end() || it->second->generation != generation) {
LOG(INFO) << "Ignore JoinGroupCallPresentationQuery response with " << input_group_call_id << " and generation "
<< generation;
return;
}
auto promise = std::move(it->second->promise);
pending_join_presentation_requests_.erase(it);
string params = UpdatesManager::extract_join_group_call_presentation_params(updates.get());
if (params.empty()) {
return promise.set_error(
Status::Error(500, "Wrong start group call screen sharing response received: parameters are missing"));
}
td_->updates_manager_->on_get_updates(
std::move(updates), PromiseCreator::lambda([params = std::move(params), promise = std::move(promise)](
Unit) mutable { promise.set_value(std::move(params)); }));
}
bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response) { bool GroupCallManager::on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response) {
auto it = pending_join_requests_.find(input_group_call_id); auto it = pending_join_requests_.find(input_group_call_id);
if (it == pending_join_requests_.end()) { if (it == pending_join_requests_.end()) {
@ -3459,11 +3576,11 @@ void GroupCallManager::discard_group_call(GroupCallId group_call_id, Promise<Uni
td_->create_handler<DiscardGroupCallQuery>(std::move(promise))->send(input_group_call_id); td_->create_handler<DiscardGroupCallQuery>(std::move(promise))->send(input_group_call_id);
} }
void GroupCallManager::on_update_group_call_connection(bool is_presentation, string &&connection_params) { void GroupCallManager::on_update_group_call_connection(string &&connection_params) {
if (!pending_group_call_join_params_[is_presentation].empty()) { if (!pending_group_call_join_params_.empty()) {
LOG(ERROR) << "Receive duplicate connection params for " << (is_presentation ? "pesentation" : "video"); LOG(ERROR) << "Receive duplicate connection params";
} }
pending_group_call_join_params_[is_presentation] = std::move(connection_params); pending_group_call_join_params_ = std::move(connection_params);
} }
void GroupCallManager::on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id) { void GroupCallManager::on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id) {
@ -3602,8 +3719,8 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
return {}; return {};
} }
string join_params = std::move(pending_group_call_join_params_[0]); string join_params = std::move(pending_group_call_join_params_);
pending_group_call_join_params_[0].clear(); pending_group_call_join_params_.clear();
bool need_update = false; bool need_update = false;
auto *group_call = add_group_call(input_group_call_id, dialog_id); auto *group_call = add_group_call(input_group_call_id, dialog_id);

View File

@ -64,9 +64,11 @@ class GroupCallManager : public Actor {
void start_scheduled_group_call(GroupCallId group_call_id, Promise<Unit> &&promise); void start_scheduled_group_call(GroupCallId group_call_id, Promise<Unit> &&promise);
void join_group_call(GroupCallId group_call_id, DialogId as_dialog_id, int32 audio_source, const string &payload, void join_group_call(GroupCallId group_call_id, DialogId as_dialog_id, int32 audio_source, string &&payload,
bool is_muted, const string &invite_hash, Promise<string> &&promise); bool is_muted, const string &invite_hash, Promise<string> &&promise);
void start_group_call_screen_sharing(GroupCallId group_call_id, string &&payload, Promise<string> &&promise);
void set_group_call_title(GroupCallId group_call_id, string title, Promise<Unit> &&promise); void set_group_call_title(GroupCallId group_call_id, string title, Promise<Unit> &&promise);
void toggle_group_call_start_subscribed(GroupCallId group_call_id, bool start_subscribed, Promise<Unit> &&promise); void toggle_group_call_start_subscribed(GroupCallId group_call_id, bool start_subscribed, Promise<Unit> &&promise);
@ -102,7 +104,7 @@ class GroupCallManager : public Actor {
void on_update_dialog_about(DialogId dialog_id, const string &about, bool from_server); void on_update_dialog_about(DialogId dialog_id, const string &about, bool from_server);
void on_update_group_call_connection(bool is_presentation, string &&connection_params); void on_update_group_call_connection(string &&connection_params);
void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id); void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id);
@ -120,6 +122,9 @@ class GroupCallManager : public Actor {
void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation, void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise); tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise);
void process_join_group_call_presentation_response(InputGroupCallId input_group_call_id, uint64 generation,
tl_object_ptr<telegram_api::Updates> &&updates, Status status);
private: private:
struct GroupCall; struct GroupCall;
struct GroupCallParticipants; struct GroupCallParticipants;
@ -229,6 +234,8 @@ class GroupCallManager : public Actor {
int32 cancel_join_group_call_request(InputGroupCallId input_group_call_id); int32 cancel_join_group_call_request(InputGroupCallId input_group_call_id);
int32 cancel_join_group_call_presentation_request(InputGroupCallId input_group_call_id);
bool on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response); bool on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response);
void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error); void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error);
@ -325,7 +332,7 @@ class GroupCallManager : public Actor {
std::unordered_map<InputGroupCallId, unique_ptr<GroupCall>, InputGroupCallIdHash> group_calls_; std::unordered_map<InputGroupCallId, unique_ptr<GroupCall>, InputGroupCallIdHash> group_calls_;
string pending_group_call_join_params_[2]; string pending_group_call_join_params_;
std::unordered_map<InputGroupCallId, unique_ptr<GroupCallParticipants>, InputGroupCallIdHash> std::unordered_map<InputGroupCallId, unique_ptr<GroupCallParticipants>, InputGroupCallIdHash>
group_call_participants_; group_call_participants_;
@ -337,6 +344,8 @@ class GroupCallManager : public Actor {
load_group_call_queries_; load_group_call_queries_;
std::unordered_map<InputGroupCallId, unique_ptr<PendingJoinRequest>, InputGroupCallIdHash> pending_join_requests_; std::unordered_map<InputGroupCallId, unique_ptr<PendingJoinRequest>, InputGroupCallIdHash> pending_join_requests_;
std::unordered_map<InputGroupCallId, unique_ptr<PendingJoinRequest>, InputGroupCallIdHash>
pending_join_presentation_requests_;
uint64 join_group_request_generation_ = 0; uint64 join_group_request_generation_ = 0;
uint64 toggle_recording_generation_ = 0; uint64 toggle_recording_generation_ = 0;

View File

@ -6035,6 +6035,21 @@ void Td::on_request(uint64 id, td_api::joinGroupCall &request) {
request.invite_hash_, std::move(query_promise)); request.invite_hash_, std::move(query_promise));
} }
void Td::on_request(uint64 id, td_api::startGroupCallScreenSharing &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.payload_);
CREATE_REQUEST_PROMISE();
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<string> result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
promise.set_value(make_tl_object<td_api::text>(result.move_as_ok()));
}
});
group_call_manager_->start_group_call_screen_sharing(GroupCallId(request.group_call_id_), std::move(request.payload_),
std::move(query_promise));
}
void Td::on_request(uint64 id, td_api::setGroupCallTitle &request) { void Td::on_request(uint64 id, td_api::setGroupCallTitle &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CLEAN_INPUT_STRING(request.title_); CLEAN_INPUT_STRING(request.title_);

View File

@ -715,6 +715,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::joinGroupCall &request); void on_request(uint64 id, td_api::joinGroupCall &request);
void on_request(uint64 id, td_api::startGroupCallScreenSharing &request);
void on_request(uint64 id, td_api::setGroupCallTitle &request); void on_request(uint64 id, td_api::setGroupCallTitle &request);
void on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request); void on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request);

View File

@ -1031,6 +1031,20 @@ vector<InputGroupCallId> UpdatesManager::get_update_new_group_call_ids(const tel
return input_group_call_ids; return input_group_call_ids;
} }
string UpdatesManager::extract_join_group_call_presentation_params(telegram_api::Updates *updates_ptr) {
auto updates = get_updates(updates_ptr);
for (auto it = updates->begin(); it != updates->end(); ++it) {
auto *update = it->get();
if (update->get_id() == telegram_api::updateGroupCallConnection::ID &&
static_cast<const telegram_api::updateGroupCallConnection *>(update)->presentation_) {
string result = std::move(static_cast<telegram_api::updateGroupCallConnection *>(update)->params_->data_);
updates->erase(it);
return result;
}
}
return string();
}
vector<DialogId> UpdatesManager::get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr) { vector<DialogId> UpdatesManager::get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr) {
vector<DialogId> dialog_ids; vector<DialogId> dialog_ids;
auto updates = get_updates(updates_ptr); auto updates = get_updates(updates_ptr);
@ -2836,8 +2850,12 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePhoneCallSignal
} }
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCallConnection> update, Promise<Unit> &&promise) { void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCallConnection> update, Promise<Unit> &&promise) {
send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call_connection, update->presentation_, if (update->presentation_) {
std::move(update->params_->data_)); LOG(ERROR) << "Receive unexpected updateGroupCallConnection";
} else {
send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call_connection,
std::move(update->params_->data_));
}
promise.set_value(Unit()); promise.set_value(Unit());
} }

View File

@ -104,6 +104,8 @@ class UpdatesManager : public Actor {
static vector<InputGroupCallId> get_update_new_group_call_ids(const telegram_api::Updates *updates_ptr); static vector<InputGroupCallId> get_update_new_group_call_ids(const telegram_api::Updates *updates_ptr);
static string extract_join_group_call_presentation_params(telegram_api::Updates *updates_ptr);
static vector<DialogId> get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr); static vector<DialogId> get_update_notify_settings_dialog_ids(const telegram_api::Updates *updates_ptr);
static vector<DialogId> get_chat_dialog_ids(const telegram_api::Updates *updates_ptr); static vector<DialogId> get_chat_dialog_ids(const telegram_api::Updates *updates_ptr);

View File

@ -2691,7 +2691,7 @@ class CliClient final : public Actor {
} else if (op == "tgcesn" || op == "tgcesne") { } else if (op == "tgcesn" || op == "tgcesne") {
send_request(td_api::make_object<td_api::toggleGroupCallEnabledStartNotification>(as_group_call_id(args), send_request(td_api::make_object<td_api::toggleGroupCallEnabledStartNotification>(as_group_call_id(args),
op == "tgcesne")); op == "tgcesne"));
} else if (op == "jgc" || op == "jgcv") { } else if (op == "jgc" || op == "jgcv" || op == "sgcss") {
string group_call_id; string group_call_id;
string participant_id; string participant_id;
string invite_hash; string invite_hash;
@ -2711,9 +2711,14 @@ class CliClient final : public Actor {
"ietf:params:rtp-hdrext:ssrc-audio-level\"}],\"ssrc-groups\":[{\"sources\":[1,2],\"semantics\":\"SIM\"},{" "ietf:params:rtp-hdrext:ssrc-audio-level\"}],\"ssrc-groups\":[{\"sources\":[1,2],\"semantics\":\"SIM\"},{"
"\"sources\":[3,4],\"semantics\":\"FID\"}]}"; "\"sources\":[3,4],\"semantics\":\"FID\"}]}";
} }
send_request(td_api::make_object<td_api::joinGroupCall>(as_group_call_id(group_call_id), if (op == "sgcss") {
as_message_sender(participant_id), group_call_source_, send_request(td_api::make_object<td_api::startGroupCallScreenSharing>(as_group_call_id(group_call_id),
std::move(payload), true, invite_hash)); std::move(payload)));
} else {
send_request(td_api::make_object<td_api::joinGroupCall>(as_group_call_id(group_call_id),
as_message_sender(participant_id), group_call_source_,
std::move(payload), true, invite_hash));
}
} else if (op == "sgct") { } else if (op == "sgct") {
string chat_id; string chat_id;
string title; string title;