Try migrating mute/video state.

This commit is contained in:
John Preston 2025-04-02 00:13:14 +05:00
parent 6528567746
commit eb06c0da08
9 changed files with 118 additions and 71 deletions

View file

@ -437,20 +437,24 @@ void Call::acceptConferenceInvite() {
const auto limit = 5;
const auto messageId = _conferenceInviteMsgId;
const auto session = &_user->session();
auto info = StartConferenceInfo{
.joinMessageId = messageId,
.migrating = true,
.muted = muted(),
.videoCapture = isSharingVideo() ? _videoCapture : nullptr,
.videoCaptureScreenId = screenSharingDeviceId(),
};
session->api().request(MTPphone_GetGroupCall(
MTP_inputGroupCallInviteMessage(MTP_int(messageId.bare)),
MTP_int(limit)
)).done([session, messageId](const MTPphone_GroupCall &result) {
)).done([session, messageId, info](const MTPphone_GroupCall &result) {
result.data().vcall().match([&](const auto &data) {
const auto call = session->data().sharedConferenceCall(
auto copy = info;
copy.call = session->data().sharedConferenceCall(
data.vid().v,
data.vaccess_hash().v);
call->processFullCall(result);
Core::App().calls().startOrJoinConferenceCall({
.call = call,
.joinMessageId = messageId,
.migrating = true,
});
copy.call->processFullCall(result);
Core::App().calls().startOrJoinConferenceCall(std::move(copy));
});
}).fail(crl::guard(this, [=](const MTP::Error &error) {
handleRequestError(error.type());
@ -561,7 +565,8 @@ void Call::setupOutgoingVideo() {
_videoOutgoing->setState(Webrtc::VideoState::Inactive);
} else if (_state.current() != State::Established
&& (state != Webrtc::VideoState::Inactive)
&& (started == Webrtc::VideoState::Inactive)) {
&& (started == Webrtc::VideoState::Inactive)
&& !conferenceInvite()) {
_errors.fire({ ErrorType::NotStartedCall });
_videoOutgoing->setState(Webrtc::VideoState::Inactive);
} else if (state != Webrtc::VideoState::Inactive
@ -1451,6 +1456,11 @@ void Call::toggleScreenSharing(std::optional<QString> uniqueId) {
_videoOutgoing->setState(Webrtc::VideoState::Active);
}
auto Call::peekVideoCapture() const
-> std::shared_ptr<tgcalls::VideoCaptureInterface> {
return _videoCapture;
}
auto Call::playbackDeviceIdValue() const
-> rpl::producer<Webrtc::DeviceResolvedId> {
return _playbackDeviceId.value();

View file

@ -247,6 +247,8 @@ public:
[[nodiscard]] QString screenSharingDeviceId() const;
void toggleCameraSharing(bool enabled);
void toggleScreenSharing(std::optional<QString> uniqueId);
[[nodiscard]] auto peekVideoCapture() const
-> std::shared_ptr<tgcalls::VideoCaptureInterface>;
[[nodiscard]] auto playbackDeviceIdValue() const
-> rpl::producer<Webrtc::DeviceResolvedId>;

View file

@ -235,20 +235,13 @@ void Instance::startOrJoinGroupCall(
});
}
void Instance::startOrJoinConferenceCall(StartConferenceCallArgs args) {
void Instance::startOrJoinConferenceCall(StartConferenceInfo args) {
destroyCurrentCall(
args.migrating ? args.call.get() : nullptr,
args.migrating ? args.linkSlug : QString());
const auto session = &args.call->peer()->session();
auto call = std::make_unique<GroupCall>(
_delegate.get(),
Calls::Group::ConferenceInfo{
.call = std::move(args.call),
.e2e = std::move(args.e2e),
.linkSlug = args.linkSlug,
.joinMessageId = args.joinMessageId,
});
auto call = std::make_unique<GroupCall>(_delegate.get(), args);
const auto raw = call.get();
session->account().sessionChanges(

View file

@ -45,10 +45,6 @@ namespace tgcalls {
class VideoCaptureInterface;
} // namespace tgcalls
namespace TdE2E {
class Call;
} // namespace TdE2E
namespace Calls {
class Call;
@ -57,6 +53,7 @@ class GroupCall;
class Panel;
struct DhConfig;
struct InviteRequest;
struct StartConferenceInfo;
struct StartGroupCallArgs {
enum class JoinConfirm {
@ -69,15 +66,6 @@ struct StartGroupCallArgs {
bool scheduleNeeded = false;
};
struct StartConferenceCallArgs {
std::shared_ptr<Data::GroupCall> call;
std::shared_ptr<TdE2E::Call> e2e;
QString linkSlug;
MsgId joinMessageId;
std::vector<InviteRequest> invite;
bool migrating = false;
};
struct ConferenceInviteMessages {
base::flat_set<MsgId> incoming;
base::flat_set<MsgId> outgoing;
@ -97,7 +85,7 @@ public:
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer,
StartGroupCallArgs args);
void startOrJoinConferenceCall(StartConferenceCallArgs args);
void startOrJoinConferenceCall(StartConferenceInfo args);
void showStartWithRtmp(
std::shared_ptr<Ui::Show> show,
not_null<PeerData*> peer);

View file

@ -477,9 +477,16 @@ void Panel::initControls() {
Group::MakeConferenceCall({
.show = uiShow(),
.finished = finish,
.invite = std::move(users),
.joining = true,
.migrating = true,
.info = {
.invite = std::move(users),
.migrating = true,
.muted = call->muted(),
.videoCapture = (call->isSharingVideo()
? call->peekVideoCapture()
: nullptr),
.videoCaptureScreenId = call->screenSharingDeviceId(),
},
});
};
const auto invite = crl::guard(call, [=](

View file

@ -58,13 +58,10 @@ constexpr auto kMaxMediumQualities = 16; // 4 Fulls or 16 Mediums.
constexpr auto kShortPollChainBlocksPerRequest = 50;
[[nodiscard]] const Data::GroupCallParticipant *LookupParticipant(
not_null<PeerData*> peer,
CallId id,
not_null<GroupCall*> call,
not_null<PeerData*> participantPeer) {
const auto call = peer->groupCall();
return (id && call && call->id() == id)
? call->participantByPeer(participantPeer)
: nullptr;
const auto real = call->lookupReal();
return real ? real->participantByPeer(participantPeer) : nullptr;
}
[[nodiscard]] double TimestampFromMsgId(mtpMsgId msgId) {
@ -578,7 +575,7 @@ GroupCall::GroupCall(
GroupCall::GroupCall(
not_null<Delegate*> delegate,
Group::ConferenceInfo info)
StartConferenceInfo info)
: GroupCall(delegate, Group::JoinInfo{
.peer = info.call->peer(),
.joinAs = info.call->peer(),
@ -588,7 +585,7 @@ GroupCall::GroupCall(
GroupCall::GroupCall(
not_null<Delegate*> delegate,
Group::JoinInfo join,
Group::ConferenceInfo conference,
StartConferenceInfo conference,
const MTPInputGroupCall &inputCall)
: _delegate(delegate)
, _conferenceCall(std::move(conference.call))
@ -682,6 +679,13 @@ GroupCall::GroupCall(
setupOutgoingVideo();
if (_conferenceCall) {
setupConferenceCall();
if (conference.migrating) {
if (!conference.muted) {
setMuted(MuteState::Active);
}
_migratedConferenceInfo = std::make_shared<StartConferenceInfo>(
std::move(conference));
}
}
if (_id) {
@ -694,6 +698,40 @@ GroupCall::GroupCall(
}
}
void GroupCall::processMigration(StartConferenceInfo conference) {
if (!conference.videoCapture) {
return;
}
const auto weak = base::make_weak(this);
if (!conference.videoCaptureScreenId.isEmpty()) {
_screenCapture = std::move(conference.videoCapture);
_screenDeviceId = conference.videoCaptureScreenId;
_screenCapture->setOnFatalError([=] {
crl::on_main(weak, [=] {
emitShareScreenError(Error::ScreenFailed);
});
});
_screenCapture->setOnPause([=](bool paused) {
crl::on_main(weak, [=] {
if (isSharingScreen()) {
_screenState = paused
? Webrtc::VideoState::Paused
: Webrtc::VideoState::Active;
}
});
});
_screenState = Webrtc::VideoState::Active;
} else {
_cameraCapture = std::move(conference.videoCapture);
_cameraCapture->setOnFatalError([=] {
crl::on_main(weak, [=] {
emitShareCameraError(Error::CameraFailed);
});
});
_cameraState = Webrtc::VideoState::Active;
}
}
GroupCall::~GroupCall() {
destroyScreencast();
destroyController();
@ -1578,6 +1616,9 @@ void GroupCall::sendJoinRequest() {
sendOutboundBlock(base::take(_pendingOutboundBlock));
}
}
if (const auto once = base::take(_migratedConferenceInfo)) {
processMigration(*once);
}
}).fail([=](const MTP::Error &error) {
const auto type = error.type();
if (_e2e) {
@ -1885,7 +1926,7 @@ void GroupCall::applyParticipantLocally(
not_null<PeerData*> participantPeer,
bool mute,
std::optional<int> volume) {
const auto participant = LookupParticipant(_peer, _id, participantPeer);
const auto participant = LookupParticipant(this, participantPeer);
if (!participant || !participant->ssrc) {
return;
}
@ -2370,7 +2411,7 @@ void GroupCall::applyOtherParticipantUpdate(
}
const auto participantPeer = _peer->owner().peer(
peerFromMTP(data.vpeer()));
if (!LookupParticipant(_peer, _id, participantPeer)) {
if (!LookupParticipant(this, participantPeer)) {
return;
}
_otherParticipantStateValue.fire(Group::ParticipantState{
@ -3686,7 +3727,7 @@ void GroupCall::editParticipant(
not_null<PeerData*> participantPeer,
bool mute,
std::optional<int> volume) {
const auto participant = LookupParticipant(_peer, _id, participantPeer);
const auto participant = LookupParticipant(this, participantPeer);
if (!participant) {
return;
}

View file

@ -62,6 +62,7 @@ enum class Error;
struct InviteRequest;
struct InviteResult;
struct StartConferenceInfo;
enum class MuteState {
Active,
@ -225,9 +226,7 @@ public:
not_null<Delegate*> delegate,
Group::JoinInfo info,
const MTPInputGroupCall &inputCall);
GroupCall(
not_null<Delegate*> delegate,
Group::ConferenceInfo info);
GroupCall(not_null<Delegate*> delegate, StartConferenceInfo info);
~GroupCall();
[[nodiscard]] CallId id() const {
@ -505,7 +504,7 @@ private:
GroupCall(
not_null<Delegate*> delegate,
Group::JoinInfo join,
Group::ConferenceInfo conference,
StartConferenceInfo conference,
const MTPInputGroupCall &inputCall);
void broadcastPartStart(std::shared_ptr<LoadPartTask> task);
@ -620,6 +619,8 @@ private:
void markTrackPaused(const VideoEndpoint &endpoint, bool paused);
void markTrackShown(const VideoEndpoint &endpoint, bool shown);
void processMigration(StartConferenceInfo conference);
[[nodiscard]] int activeVideoSendersCount() const;
[[nodiscard]] MTPInputGroupCall inputCall() const;
@ -629,6 +630,7 @@ private:
const std::shared_ptr<Data::GroupCall> _conferenceCall;
std::shared_ptr<TdE2E::Call> _e2e;
QByteArray _pendingOutboundBlock;
std::shared_ptr<StartConferenceInfo> _migratedConferenceInfo;
not_null<PeerData*> _peer; // Can change in legacy group migration.
rpl::event_stream<PeerData*> _peerStream;

View file

@ -392,7 +392,7 @@ void ExportConferenceCallLink(
std::shared_ptr<Data::GroupCall> call,
ConferenceCallLinkArgs &&args) {
const auto session = &show->session();
const auto invite = std::move(args.invite);
const auto info = std::move(args.info);
const auto finished = std::move(args.finished);
using Flag = MTPphone_ExportGroupCallInvite::Flag;
@ -403,12 +403,10 @@ void ExportConferenceCallLink(
const auto link = qs(result.data().vlink());
if (args.joining) {
if (auto slug = ExtractConferenceSlug(link); !slug.isEmpty()) {
Core::App().calls().startOrJoinConferenceCall({
.call = call,
.linkSlug = std::move(slug),
.invite = invite,
.migrating = args.migrating,
});
auto copy = info;
copy.call = call;
copy.linkSlug = std::move(slug);
Core::App().calls().startOrJoinConferenceCall(info);
}
if (const auto onstack = finished) {
finished(QString());
@ -435,8 +433,7 @@ void MakeConferenceCall(ConferenceFactoryArgs &&args) {
const auto show = std::move(args.show);
const auto finished = std::move(args.finished);
const auto joining = args.joining;
const auto migrating = args.migrating;
const auto invite = std::move(args.invite);
const auto info = std::move(args.info);
const auto session = &show->session();
session->api().request(MTPphone_CreateConferenceCall(
MTP_int(base::RandomValue<int32>())
@ -449,9 +446,8 @@ void MakeConferenceCall(ConferenceFactoryArgs &&args) {
Calls::Group::ExportConferenceCallLink(show, call, {
.initial = true,
.joining = joining,
.migrating = migrating,
.finished = finished,
.invite = invite,
.info = info,
});
});
}).fail([=](const MTP::Error &error) {

View file

@ -37,6 +37,10 @@ namespace TdE2E {
class Call;
} // namespace TdE2E
namespace tgcalls {
class VideoCaptureInterface;
} // namespace tgcalls
namespace Window {
class SessionController;
} // namespace Window
@ -47,12 +51,25 @@ struct InviteRequest {
not_null<UserData*> user;
bool video = false;
};
struct InviteResult {
std::vector<not_null<UserData*>> invited;
std::vector<not_null<UserData*>> alreadyIn;
std::vector<not_null<UserData*>> privacyRestricted;
};
struct StartConferenceInfo {
std::shared_ptr<Data::GroupCall> call;
std::shared_ptr<TdE2E::Call> e2e;
QString linkSlug;
MsgId joinMessageId;
std::vector<InviteRequest> invite;
bool migrating = false;
bool muted = false;
std::shared_ptr<tgcalls::VideoCaptureInterface> videoCapture;
QString videoCaptureScreenId;
};
} // namespace Calls
namespace Calls::Group {
@ -101,13 +118,6 @@ struct JoinInfo {
bool rtmp = false;
};
struct ConferenceInfo {
std::shared_ptr<Data::GroupCall> call;
std::shared_ptr<TdE2E::Call> e2e;
QString linkSlug;
MsgId joinMessageId;
};
enum class PanelMode {
Default,
Wide,
@ -158,9 +168,8 @@ struct ConferenceCallLinkStyleOverrides {
struct ConferenceCallLinkArgs {
bool initial = false;
bool joining = false;
bool migrating = false;
Fn<void(QString)> finished;
std::vector<InviteRequest> invite;
StartConferenceInfo info;
ConferenceCallLinkStyleOverrides st;
};
void ShowConferenceCallLinkBox(
@ -177,9 +186,8 @@ void ExportConferenceCallLink(
struct ConferenceFactoryArgs {
std::shared_ptr<Main::SessionShow> show;
Fn<void(QString)> finished;
std::vector<InviteRequest> invite;
bool joining = false;
bool migrating = false;
StartConferenceInfo info;
};
void MakeConferenceCall(ConferenceFactoryArgs &&args);