mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added ability to start livestream with RTMP.
This commit is contained in:
parent
97dbb98862
commit
8909b654d3
9 changed files with 423 additions and 6 deletions
|
@ -280,6 +280,8 @@ PRIVATE
|
||||||
calls/group/calls_group_menu.h
|
calls/group/calls_group_menu.h
|
||||||
calls/group/calls_group_panel.cpp
|
calls/group/calls_group_panel.cpp
|
||||||
calls/group/calls_group_panel.h
|
calls/group/calls_group_panel.h
|
||||||
|
calls/group/calls_group_rtmp.cpp
|
||||||
|
calls/group/calls_group_rtmp.h
|
||||||
calls/group/calls_group_settings.cpp
|
calls/group/calls_group_settings.cpp
|
||||||
calls/group/calls_group_settings.h
|
calls/group/calls_group_settings.h
|
||||||
calls/group/calls_group_toasts.cpp
|
calls/group/calls_group_toasts.cpp
|
||||||
|
|
|
@ -2381,6 +2381,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_group_call_join_as_changed" = "Members of this voice chat will now see you as {name}";
|
"lng_group_call_join_as_changed" = "Members of this voice chat will now see you as {name}";
|
||||||
"lng_group_call_join_as_changed_channel" = "Members of this live stream will now see you as {name}";
|
"lng_group_call_join_as_changed_channel" = "Members of this live stream will now see you as {name}";
|
||||||
|
|
||||||
|
"lng_group_call_rtmp_title" = "Stream with other apps";
|
||||||
|
"lng_group_call_rtmp_url_subtitle" = "Server URL";
|
||||||
|
"lng_group_call_rtmp_url_copy" = "Copy Server URL";
|
||||||
|
"lng_group_call_rtmp_url_copied" = "Server URL copied to clipboard.";
|
||||||
|
"lng_group_call_rtmp_key_subtitle" = "Stream Key";
|
||||||
|
"lng_group_call_rtmp_key_copy" = "Copy Stream Key";
|
||||||
|
"lng_group_call_rtmp_key_copied" = "Stream Key copied to clipboard.";
|
||||||
|
"lng_group_call_rtmp_key_warn" = "Never share your Stream Key with anyone or show it on stream!";
|
||||||
|
"lng_group_call_rtmp_info" = "To stream video with another app, enter these Server URL and Stream Key in your streaming app.\n\nOnce you start broadcasting in your streaming app, tap Start Streaming below";
|
||||||
|
"lng_group_call_rtmp_start" = "Start Streaming";
|
||||||
|
"lng_group_call_rtmp_revoke_sure" = "Are you sure you want to revoke your Server URL and Stream Key?";
|
||||||
|
|
||||||
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
||||||
|
|
||||||
"lng_player_message_today" = "Today at {time}";
|
"lng_player_message_today" = "Today at {time}";
|
||||||
|
|
|
@ -1349,3 +1349,33 @@ groupCallRecordingSubLabelMargins: margins(8px, 22px, 8px, 22px);
|
||||||
groupCallRecordingAudioSkip: 23px;
|
groupCallRecordingAudioSkip: 23px;
|
||||||
groupCallRecordingSelectWidth: 2px;
|
groupCallRecordingSelectWidth: 2px;
|
||||||
groupCallRecordingInfoHeight: 204px;
|
groupCallRecordingInfoHeight: 204px;
|
||||||
|
|
||||||
|
groupCallRtmpCopyButton: RoundButton(defaultActiveButton) {
|
||||||
|
height: 32px;
|
||||||
|
width: -26px;
|
||||||
|
|
||||||
|
textTop: 7px;
|
||||||
|
padding: margins(0px, 12px, 0px, 15px);
|
||||||
|
}
|
||||||
|
groupCallRtmpShowButton: IconButton(defaultIconButton) {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
|
icon: icon {{ "menu/show_in_chat", menuIconFg }};
|
||||||
|
iconOver: icon {{ "menu/show_in_chat", menuIconFgOver }};
|
||||||
|
iconPosition: point(4px, 4px);
|
||||||
|
|
||||||
|
rippleAreaPosition: point(0px, 0px);
|
||||||
|
rippleAreaSize: 32px;
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: windowBgOver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupCallRtmpUrlSkip: 1px;
|
||||||
|
groupCallRtmpKeySubsectionTitleSkip: 8px;
|
||||||
|
groupCallRtmpSubsectionTitleAddPadding: margins(0px, -1px, 0px, -4px);
|
||||||
|
groupCallRtmpShowButtonPosition: point(21px, -5px);
|
||||||
|
groupCallRtmpKeyLabel: FlatLabel(boxLabel) {
|
||||||
|
minWidth: 230px;
|
||||||
|
}
|
||||||
|
groupCallRtmpTopBarMenuPosition: point(-2px, -15px);
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "calls/group/calls_group_common.h"
|
#include "calls/group/calls_group_common.h"
|
||||||
#include "calls/group/calls_choose_join_as.h"
|
#include "calls/group/calls_choose_join_as.h"
|
||||||
#include "calls/group/calls_group_call.h"
|
#include "calls/group/calls_group_call.h"
|
||||||
|
#include "calls/group/calls_group_rtmp.h"
|
||||||
#include "mtproto/mtproto_dh_utils.h"
|
#include "mtproto/mtproto_dh_utils.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -170,7 +171,8 @@ FnMut<void()> Instance::Delegate::groupCallAddAsyncWaiter() {
|
||||||
Instance::Instance()
|
Instance::Instance()
|
||||||
: _delegate(std::make_unique<Delegate>(this))
|
: _delegate(std::make_unique<Delegate>(this))
|
||||||
, _cachedDhConfig(std::make_unique<DhConfig>())
|
, _cachedDhConfig(std::make_unique<DhConfig>())
|
||||||
, _chooseJoinAs(std::make_unique<Group::ChooseJoinAsProcess>()) {
|
, _chooseJoinAs(std::make_unique<Group::ChooseJoinAsProcess>())
|
||||||
|
, _startWithRtmp(std::make_unique<Group::StartRtmpProcess>()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance::~Instance() {
|
Instance::~Instance() {
|
||||||
|
@ -202,6 +204,18 @@ void Instance::startOrJoinGroupCall(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const StartGroupCallArgs &args) {
|
const StartGroupCallArgs &args) {
|
||||||
using JoinConfirm = StartGroupCallArgs::JoinConfirm;
|
using JoinConfirm = StartGroupCallArgs::JoinConfirm;
|
||||||
|
if (args.rtmpNeeded) {
|
||||||
|
_startWithRtmp->start(peer, [=](object_ptr<Ui::BoxContent> box) {
|
||||||
|
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
|
||||||
|
}, [=](QString text) {
|
||||||
|
Ui::Toast::Show(text);
|
||||||
|
}, [=](Group::JoinInfo info) {
|
||||||
|
createGroupCall(
|
||||||
|
std::move(info),
|
||||||
|
MTP_inputGroupCall(MTPlong(), MTPlong()));
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto context = (args.confirm == JoinConfirm::Always)
|
const auto context = (args.confirm == JoinConfirm::Always)
|
||||||
? Group::ChooseJoinAsProcess::Context::JoinWithConfirm
|
? Group::ChooseJoinAsProcess::Context::JoinWithConfirm
|
||||||
: peer->groupCall()
|
: peer->groupCall()
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace Calls::Group {
|
||||||
struct JoinInfo;
|
struct JoinInfo;
|
||||||
class Panel;
|
class Panel;
|
||||||
class ChooseJoinAsProcess;
|
class ChooseJoinAsProcess;
|
||||||
|
class StartRtmpProcess;
|
||||||
} // namespace Calls::Group
|
} // namespace Calls::Group
|
||||||
|
|
||||||
namespace tgcalls {
|
namespace tgcalls {
|
||||||
|
@ -52,7 +53,8 @@ struct StartGroupCallArgs {
|
||||||
QString joinHash;
|
QString joinHash;
|
||||||
JoinConfirm confirm = JoinConfirm::IfNowInAnother;
|
JoinConfirm confirm = JoinConfirm::IfNowInAnother;
|
||||||
bool scheduleNeeded = false;
|
bool scheduleNeeded = false;
|
||||||
bool rtmp = false;
|
bool rtmpNeeded = false;
|
||||||
|
bool useRtmp = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Instance final : public base::has_weak_ptr {
|
class Instance final : public base::has_weak_ptr {
|
||||||
|
@ -150,6 +152,7 @@ private:
|
||||||
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
|
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
|
||||||
|
|
||||||
const std::unique_ptr<Group::ChooseJoinAsProcess> _chooseJoinAs;
|
const std::unique_ptr<Group::ChooseJoinAsProcess> _chooseJoinAs;
|
||||||
|
const std::unique_ptr<Group::StartRtmpProcess> _startWithRtmp;
|
||||||
|
|
||||||
base::flat_set<std::unique_ptr<crl::semaphore>> _asyncWaiters;
|
base::flat_set<std::unique_ptr<crl::semaphore>> _asyncWaiters;
|
||||||
|
|
||||||
|
|
|
@ -639,7 +639,7 @@ GroupCall::GroupCall(
|
||||||
if (_id) {
|
if (_id) {
|
||||||
join(inputCall);
|
join(inputCall);
|
||||||
} else {
|
} else {
|
||||||
start(info.scheduleDate);
|
start(info.scheduleDate, info.rtmp);
|
||||||
}
|
}
|
||||||
if (_scheduleDate) {
|
if (_scheduleDate) {
|
||||||
saveDefaultJoinAs(joinAs());
|
saveDefaultJoinAs(joinAs());
|
||||||
|
@ -1013,10 +1013,11 @@ rpl::producer<not_null<Data::GroupCall*>> GroupCall::real() const {
|
||||||
return _realChanges.events();
|
return _realChanges.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::start(TimeId scheduleDate) {
|
void GroupCall::start(TimeId scheduleDate, bool rtmp) {
|
||||||
using Flag = MTPphone_CreateGroupCall::Flag;
|
using Flag = MTPphone_CreateGroupCall::Flag;
|
||||||
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
_createRequestId = _api.request(MTPphone_CreateGroupCall(
|
||||||
MTP_flags(scheduleDate ? Flag::f_schedule_date : Flag(0)),
|
MTP_flags((scheduleDate ? Flag::f_schedule_date : Flag(0))
|
||||||
|
| (rtmp ? Flag::f_rtmp_stream : Flag(0))),
|
||||||
_peer->input,
|
_peer->input,
|
||||||
MTP_int(base::RandomValue<int32>()),
|
MTP_int(base::RandomValue<int32>()),
|
||||||
MTPstring(), // title
|
MTPstring(), // title
|
||||||
|
|
|
@ -236,7 +236,7 @@ public:
|
||||||
[[nodiscard]] Data::GroupCall *lookupReal() const;
|
[[nodiscard]] Data::GroupCall *lookupReal() const;
|
||||||
[[nodiscard]] rpl::producer<not_null<Data::GroupCall*>> real() const;
|
[[nodiscard]] rpl::producer<not_null<Data::GroupCall*>> real() const;
|
||||||
|
|
||||||
void start(TimeId scheduleDate);
|
void start(TimeId scheduleDate, bool rtmp);
|
||||||
void hangup();
|
void hangup();
|
||||||
void discard();
|
void discard();
|
||||||
void rejoinAs(Group::JoinInfo info);
|
void rejoinAs(Group::JoinInfo info);
|
||||||
|
|
295
Telegram/SourceFiles/calls/group/calls_group_rtmp.cpp
Normal file
295
Telegram/SourceFiles/calls/group/calls_group_rtmp.cpp
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "calls/group/calls_group_rtmp.h"
|
||||||
|
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "calls/group/calls_group_common.h"
|
||||||
|
#include "data/data_peer.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_account.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "settings/settings_common.h" // AddDivider.
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
|
#include "ui/layers/generic_box.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
|
#include "ui/widgets/buttons.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
#include "styles/style_boxes.h"
|
||||||
|
#include "styles/style_calls.h"
|
||||||
|
#include "styles/style_info.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QStyle>
|
||||||
|
|
||||||
|
namespace Calls::Group {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void StartWithBox(
|
||||||
|
not_null<Ui::GenericBox*> box,
|
||||||
|
Fn<void()> done,
|
||||||
|
Fn<void()> revoke,
|
||||||
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
|
||||||
|
Fn<void(QString)> showToast,
|
||||||
|
rpl::producer<StartRtmpProcess::Data> &&data) {
|
||||||
|
struct State {
|
||||||
|
rpl::variable<bool> hidden = true;
|
||||||
|
rpl::variable<QString> key;
|
||||||
|
rpl::variable<QString> url;
|
||||||
|
base::unique_qptr<Ui::PopupMenu> menu;
|
||||||
|
bool warned = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto &rowPadding = st::boxRowPadding;
|
||||||
|
|
||||||
|
const auto passChar = QChar(box->style()->styleHint(
|
||||||
|
QStyle::SH_LineEdit_PasswordCharacter));
|
||||||
|
const auto state = box->lifetime().make_state<State>();
|
||||||
|
state->key = rpl::duplicate(
|
||||||
|
data
|
||||||
|
) | rpl::map([=](const auto &d) { return d.key; });
|
||||||
|
state->url = std::move(
|
||||||
|
data
|
||||||
|
) | rpl::map([=](const auto &d) { return d.url; });
|
||||||
|
|
||||||
|
const auto addButton = [&](
|
||||||
|
bool key,
|
||||||
|
rpl::producer<QString> &&text) {
|
||||||
|
const auto &padding = st::groupCallRtmpCopyButton.padding;
|
||||||
|
|
||||||
|
auto wrap = object_ptr<Ui::RpWidget>(box);
|
||||||
|
auto button = Ui::CreateChild<Ui::RoundButton>(
|
||||||
|
wrap.data(),
|
||||||
|
rpl::duplicate(text),
|
||||||
|
st::groupCallRtmpCopyButton);
|
||||||
|
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
|
||||||
|
button->setClickedCallback(key
|
||||||
|
? Fn<void()>([=] {
|
||||||
|
QGuiApplication::clipboard()->setText(state->key.current());
|
||||||
|
showToast(tr::lng_group_call_rtmp_key_copied(tr::now));
|
||||||
|
})
|
||||||
|
: Fn<void()>([=] {
|
||||||
|
QGuiApplication::clipboard()->setText(state->url.current());
|
||||||
|
showToast(tr::lng_group_call_rtmp_url_copied(tr::now));
|
||||||
|
}));
|
||||||
|
const auto weak = box->addRow(std::move(wrap), rowPadding);
|
||||||
|
button->heightValue(
|
||||||
|
) | rpl::start_with_next([=](int height) {
|
||||||
|
weak->resize(weak->width(), height);
|
||||||
|
}, box->lifetime());
|
||||||
|
return weak;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto addLabel = [&](
|
||||||
|
rpl::producer<QString> &&text,
|
||||||
|
const style::FlatLabel &st) {
|
||||||
|
const auto label = box->addRow(
|
||||||
|
object_ptr<Ui::FlatLabel>(box, std::move(text), st),
|
||||||
|
st::boxRowPadding);
|
||||||
|
label->setSelectable(true);
|
||||||
|
label->setBreakEverywhere(true);
|
||||||
|
return label;
|
||||||
|
};
|
||||||
|
|
||||||
|
box->setTitle(tr::lng_group_call_rtmp_title());
|
||||||
|
|
||||||
|
// Server URL.
|
||||||
|
Settings::AddSubsectionTitle(
|
||||||
|
box->verticalLayout(),
|
||||||
|
tr::lng_group_call_rtmp_url_subtitle(),
|
||||||
|
st::groupCallRtmpSubsectionTitleAddPadding);
|
||||||
|
auto urlLabelContent = state->url.value();
|
||||||
|
addLabel(std::move(urlLabelContent), st::boxLabel);
|
||||||
|
box->addSkip(st::groupCallRtmpUrlSkip);
|
||||||
|
addButton(false, tr::lng_group_call_rtmp_url_copy());
|
||||||
|
//
|
||||||
|
|
||||||
|
Settings::AddDivider(box->verticalLayout());
|
||||||
|
|
||||||
|
// Stream Key.
|
||||||
|
box->addSkip(st::groupCallRtmpKeySubsectionTitleSkip);
|
||||||
|
Settings::AddSubsectionTitle(
|
||||||
|
box->verticalLayout(),
|
||||||
|
tr::lng_group_call_rtmp_key_subtitle(),
|
||||||
|
st::groupCallRtmpSubsectionTitleAddPadding);
|
||||||
|
|
||||||
|
auto keyLabelContent = rpl::combine(
|
||||||
|
state->hidden.value(),
|
||||||
|
state->key.value()
|
||||||
|
) | rpl::map([passChar](bool hidden, const QString &key) {
|
||||||
|
return hidden
|
||||||
|
? QString().fill(passChar, int(key.size()))
|
||||||
|
: key;
|
||||||
|
});
|
||||||
|
const auto streamKeyLabel = addLabel(
|
||||||
|
std::move(keyLabelContent),
|
||||||
|
st::boxLabel);
|
||||||
|
const auto streamKeyButton = Ui::CreateChild<Ui::IconButton>(
|
||||||
|
box.get(),
|
||||||
|
st::groupCallRtmpShowButton);
|
||||||
|
|
||||||
|
streamKeyLabel->topValue(
|
||||||
|
) | rpl::start_with_next([=, right = rowPadding.right()](int top) {
|
||||||
|
streamKeyButton->moveToRight(
|
||||||
|
st::groupCallRtmpShowButtonPosition.x(),
|
||||||
|
top + st::groupCallRtmpShowButtonPosition.y());
|
||||||
|
streamKeyButton->raise();
|
||||||
|
}, box->lifetime());
|
||||||
|
streamKeyButton->addClickHandler([=] {
|
||||||
|
if (!state->warned && state->hidden.current()) {
|
||||||
|
showBox(Box<Ui::ConfirmBox>(
|
||||||
|
tr::lng_group_call_rtmp_key_warn(tr::now),
|
||||||
|
tr::lng_from_request_understand(tr::now),
|
||||||
|
tr::lng_close(tr::now),
|
||||||
|
[=](Fn<void()> &&close) {
|
||||||
|
state->warned = true;
|
||||||
|
state->hidden = !state->hidden.current();
|
||||||
|
close();
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
state->hidden = !state->hidden.current();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addButton(true, tr::lng_group_call_rtmp_key_copy());
|
||||||
|
//
|
||||||
|
|
||||||
|
Settings::AddDividerText(
|
||||||
|
box->verticalLayout(),
|
||||||
|
tr::lng_group_call_rtmp_info());
|
||||||
|
|
||||||
|
box->addButton(tr::lng_group_call_rtmp_start(), done);
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
box->setWidth(st::infoDesiredWidth);
|
||||||
|
{
|
||||||
|
const auto top = box->addTopButton(st::infoTopBarMenu);
|
||||||
|
top->setClickedCallback([=] {
|
||||||
|
state->menu = base::make_unique_q<Ui::PopupMenu>(
|
||||||
|
top,
|
||||||
|
st::popupMenuWithIcons);
|
||||||
|
state->menu->addAction(
|
||||||
|
tr::lng_group_invite_context_revoke(tr::now),
|
||||||
|
revoke,
|
||||||
|
&st::menuIconRemove);
|
||||||
|
state->menu->moveToRight(
|
||||||
|
st::groupCallRtmpTopBarMenuPosition.x(),
|
||||||
|
st::groupCallRtmpTopBarMenuPosition.y());
|
||||||
|
state->menu->setForcedOrigin(
|
||||||
|
Ui::PanelAnimation::Origin::TopRight);
|
||||||
|
state->menu->popup(QCursor::pos());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
StartRtmpProcess::~StartRtmpProcess() {
|
||||||
|
if (_request) {
|
||||||
|
_request->peer->session().api().request(_request->id).cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRtmpProcess::start(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
|
||||||
|
Fn<void(QString)> showToast,
|
||||||
|
Fn<void(JoinInfo)> done) {
|
||||||
|
Expects(done != nullptr);
|
||||||
|
|
||||||
|
const auto session = &peer->session();
|
||||||
|
if (_request) {
|
||||||
|
if (_request->peer == peer) {
|
||||||
|
_request->showBox = std::move(showBox);
|
||||||
|
_request->showToast = std::move(showToast);
|
||||||
|
_request->done = std::move(done);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
session->api().request(_request->id).cancel();
|
||||||
|
_request = nullptr;
|
||||||
|
}
|
||||||
|
_request = std::make_unique<RtmpRequest>(
|
||||||
|
RtmpRequest{
|
||||||
|
.peer = peer,
|
||||||
|
.showBox = std::move(showBox),
|
||||||
|
.showToast = std::move(showToast),
|
||||||
|
.done = std::move(done) });
|
||||||
|
session->account().sessionChanges(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
_request = nullptr;
|
||||||
|
}, _request->lifetime);
|
||||||
|
|
||||||
|
requestUrl(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRtmpProcess::requestUrl(bool revoke) {
|
||||||
|
const auto session = &_request->peer->session();
|
||||||
|
_request->id = session->api().request(MTPphone_GetGroupCallStreamRtmpUrl(
|
||||||
|
_request->peer->input,
|
||||||
|
MTP_bool(revoke)
|
||||||
|
)).done([=](const MTPphone_GroupCallStreamRtmpUrl &result) {
|
||||||
|
auto data = result.match([&](
|
||||||
|
const MTPDphone_groupCallStreamRtmpUrl &data) {
|
||||||
|
return Data{ .url = qs(data.vurl()), .key = qs(data.vkey()) };
|
||||||
|
});
|
||||||
|
processUrl(std::move(data));
|
||||||
|
}).fail([=] {
|
||||||
|
_request->showToast(Lang::Hard::ServerError());
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRtmpProcess::processUrl(Data data) {
|
||||||
|
if (!_request->box) {
|
||||||
|
createBox();
|
||||||
|
}
|
||||||
|
_request->data = std::move(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRtmpProcess::finish(JoinInfo info) {
|
||||||
|
const auto done = std::move(_request->done);
|
||||||
|
const auto box = _request->box;
|
||||||
|
_request = nullptr;
|
||||||
|
done(std::move(info));
|
||||||
|
if (const auto strong = box.data()) {
|
||||||
|
strong->closeBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRtmpProcess::createBox() {
|
||||||
|
auto done = [=] {
|
||||||
|
const auto peer = _request->peer;
|
||||||
|
finish({ .peer = peer, .joinAs = peer, .rtmp = true });
|
||||||
|
};
|
||||||
|
auto revoke = [=] {
|
||||||
|
const auto guard = base::make_weak(&_request->guard);
|
||||||
|
_request->showBox(Box<Ui::ConfirmBox>(
|
||||||
|
tr::lng_group_call_rtmp_revoke_sure(tr::now),
|
||||||
|
tr::lng_group_invite_context_revoke(tr::now),
|
||||||
|
crl::guard(guard, [=](Fn<void()> &&close) {
|
||||||
|
requestUrl(true);
|
||||||
|
close();
|
||||||
|
})));
|
||||||
|
};
|
||||||
|
auto object = Box(
|
||||||
|
StartWithBox,
|
||||||
|
std::move(done),
|
||||||
|
std::move(revoke),
|
||||||
|
_request->showBox,
|
||||||
|
_request->showToast,
|
||||||
|
_request->data.value());
|
||||||
|
object->boxClosing(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
_request = nullptr;
|
||||||
|
}, _request->lifetime);
|
||||||
|
_request->box = Ui::MakeWeak(object.data());
|
||||||
|
_request->showBox(std::move(object));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Calls::Group
|
60
Telegram/SourceFiles/calls/group/calls_group_rtmp.h
Normal file
60
Telegram/SourceFiles/calls/group/calls_group_rtmp.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/weak_ptr.h"
|
||||||
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
|
class PeerData;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BoxContent;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Calls::Group {
|
||||||
|
|
||||||
|
struct JoinInfo;
|
||||||
|
|
||||||
|
class StartRtmpProcess final {
|
||||||
|
public:
|
||||||
|
StartRtmpProcess() = default;
|
||||||
|
~StartRtmpProcess();
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
QString url;
|
||||||
|
QString key;
|
||||||
|
};
|
||||||
|
|
||||||
|
void start(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
|
||||||
|
Fn<void(QString)> showToast,
|
||||||
|
Fn<void(JoinInfo)> done);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void requestUrl(bool revoke);
|
||||||
|
void processUrl(Data data);
|
||||||
|
void createBox();
|
||||||
|
void finish(JoinInfo info);
|
||||||
|
|
||||||
|
struct RtmpRequest {
|
||||||
|
not_null<PeerData*> peer;
|
||||||
|
rpl::variable<Data> data;
|
||||||
|
Fn<void(object_ptr<Ui::BoxContent>)> showBox;
|
||||||
|
Fn<void(QString)> showToast;
|
||||||
|
Fn<void(JoinInfo)> done;
|
||||||
|
base::has_weak_ptr guard;
|
||||||
|
QPointer<Ui::BoxContent> box;
|
||||||
|
rpl::lifetime lifetime;
|
||||||
|
mtpRequestId id = 0;
|
||||||
|
};
|
||||||
|
std::unique_ptr<RtmpRequest> _request;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Calls::Group
|
Loading…
Add table
Reference in a new issue