Fixed crash on incoming peer calls.

This commit is contained in:
23rd 2023-03-02 08:52:24 +03:00
parent 6ae15ff264
commit 6f3dbc4305
5 changed files with 71 additions and 45 deletions

View File

@ -259,7 +259,7 @@ private:
const not_null<UserData*> _user;
MTP::Sender _api;
Type _type = Type::Outgoing;
rpl::variable<State> _state = State::WaitingUserConfirmation;
rpl::variable<State> _state = State::Starting;
rpl::variable<RemoteAudioState> _remoteAudioState =
RemoteAudioState::Active;
rpl::variable<Webrtc::VideoState> _remoteVideoState;

View File

@ -324,31 +324,52 @@ void Instance::destroyCall(not_null<Call*> call) {
}
}
void Instance::createCall(not_null<UserData*> user, Call::Type type, bool video) {
auto call = std::make_unique<Call>(_delegate.get(), user, type, video);
const auto raw = call.get();
void Instance::createCall(
not_null<UserData*> user,
Call::Type type,
bool isVideo) {
struct Performer final {
explicit Performer(Fn<void(bool, bool, const Performer &)> callback)
: callback(std::move(callback)) {
}
Fn<void(bool, bool, const Performer &)> callback;
};
const auto performer = Performer([=](
bool video,
bool isConfirmed,
const Performer &repeater) {
const auto delegate = _delegate.get();
auto call = std::make_unique<Call>(delegate, user, type, video);
if (isConfirmed) {
call->applyUserConfirmation();
}
const auto raw = call.get();
user->session().account().sessionChanges(
) | rpl::start_with_next([=] {
destroyCall(raw);
}, raw->lifetime());
user->session().account().sessionChanges(
) | rpl::start_with_next([=] {
destroyCall(raw);
}, raw->lifetime());
if (_currentCall) {
_currentCallPanel->replaceCall(raw);
std::swap(_currentCall, call);
call->hangup();
} else {
_currentCallPanel = std::make_unique<Panel>(raw);
_currentCall = std::move(call);
}
_currentCallPanel->startOutgoingRequests(
) | rpl::start_with_next([=](bool video) {
raw->applyUserConfirmation();
raw->toggleCameraSharing(video);
refreshServerConfig(&user->session());
refreshDhConfig();
}, raw->lifetime());
_currentCallChanges.fire_copy(raw);
if (_currentCall) {
_currentCallPanel->replaceCall(raw);
std::swap(_currentCall, call);
call->hangup();
} else {
_currentCallPanel = std::make_unique<Panel>(raw);
_currentCall = std::move(call);
}
if (raw->state() == Call::State::WaitingUserConfirmation) {
_currentCallPanel->startOutgoingRequests(
) | rpl::start_with_next([=](bool video) {
repeater.callback(video, true, repeater);
}, raw->lifetime());
} else {
refreshServerConfig(&user->session());
refreshDhConfig();
}
_currentCallChanges.fire_copy(raw);
});
performer.callback(isVideo, false, performer);
}
void Instance::destroyGroupCall(not_null<GroupCall*> call) {

View File

@ -113,7 +113,7 @@ private:
not_null<Media::Audio::Track*> ensureSoundLoaded(const QString &key);
void playSoundOnce(const QString &key);
void createCall(not_null<UserData*> user, CallType type, bool video);
void createCall(not_null<UserData*> user, CallType type, bool isVideo);
void destroyCall(not_null<Call*> call);
void createGroupCall(

View File

@ -80,9 +80,6 @@ Panel::Panel(not_null<Call*> call)
st::callScreencastOn,
&st::callScreencastOff))
, _camera(widget(), st::callCameraMute, &st::callCameraUnmute)
, _startVideo(
widget(),
object_ptr<Ui::CallButton>(widget(), st::callStartVideo))
, _mute(
widget(),
object_ptr<Ui::CallButton>(
@ -281,6 +278,7 @@ void Panel::initControls() {
} else if (_call->isIncomingWaiting()) {
_call->answer();
} else if (state == State::WaitingUserConfirmation) {
_startOutgoingRequests.fire(false);
} else {
_call->hangup();
}
@ -292,7 +290,6 @@ void Panel::initControls() {
};
_decline->entity()->setClickedCallback(hangupCallback);
_cancel->entity()->setClickedCallback(hangupCallback);
_startVideo->entity()->setText(tr::lng_call_start_video());
reinitWithCall(_call);
@ -334,14 +331,10 @@ rpl::lifetime &Panel::chooseSourceInstanceLifetime() {
}
rpl::producer<bool> Panel::startOutgoingRequests() const {
const auto filter = [=] {
return _startOutgoingRequests.events(
) | rpl::filter([=] {
return _call && (_call->state() == State::WaitingUserConfirmation);
};
return rpl::merge(
_startVideo->entity()->clicks(
) | rpl::filter(filter) | rpl::map_to(true),
_answerHangupRedial->clicks(
) | rpl::filter(filter) | rpl::map_to(false));
});
}
void Panel::chooseSourceAccepted(
@ -478,7 +471,9 @@ void Panel::reinitWithCall(Call *call) {
rpl::combine(
_call->stateValue(),
_call->videoOutgoing()->renderNextFrame()
rpl::single(
rpl::empty_value()
) | rpl::then(_call->videoOutgoing()->renderNextFrame())
) | rpl::start_with_next([=](State state, auto) {
if (state != State::Ended
&& state != State::EndedByOtherDevice
@ -523,7 +518,9 @@ void Panel::reinitWithCall(Call *call) {
_decline->raise();
_cancel->raise();
_camera->raise();
_startVideo->raise();
if (_startVideo) {
_startVideo->raise();
}
_mute->raise();
_powerSaveBlocker = std::make_unique<base::PowerSaveBlocker>(
@ -794,7 +791,7 @@ void Panel::updateHangupGeometry() {
_camera->moveToLeft(
hangupRight - _mute->width() + _screencast->width(),
_buttonsTop);
if (_startVideo->toggled()) {
if (_startVideo) {
_startVideo->moveToLeft(_camera->x(), _camera->y());
}
}
@ -849,12 +846,18 @@ void Panel::stateChanged(State state) {
if (isBusy) {
_powerSaveBlocker = nullptr;
}
if (_startVideo->toggled() && !isWaitingUser) {
_startVideo->toggle(false, anim::type::instant);
} else if (!_startVideo->toggled() && isWaitingUser) {
_startVideo->toggle(true, anim::type::instant);
if (_startVideo && !isWaitingUser) {
_startVideo = nullptr;
} else if (!_startVideo && isWaitingUser) {
_startVideo = base::make_unique_q<Ui::CallButton>(
widget(),
st::callStartVideo);
_startVideo->setText(tr::lng_call_start_video());
_startVideo->clicks() | rpl::map_to(true) | rpl::start_to_stream(
_startOutgoingRequests,
_startVideo->lifetime());
}
_camera->setVisible(!_startVideo->toggled());
_camera->setVisible(!_startVideo);
const auto toggleButton = [&](auto &&button, bool visible) {
button->toggle(

View File

@ -152,7 +152,7 @@ private:
Ui::Animations::Simple _hangupShownProgress;
object_ptr<Ui::FadeWrap<Ui::CallButton>> _screencast;
object_ptr<Ui::CallButton> _camera;
object_ptr<Ui::FadeWrap<Ui::CallButton>> _startVideo;
base::unique_qptr<Ui::CallButton> _startVideo;
object_ptr<Ui::FadeWrap<Ui::CallButton>> _mute;
object_ptr<Ui::FlatLabel> _name;
object_ptr<Ui::FlatLabel> _status;
@ -167,6 +167,8 @@ private:
base::Timer _updateDurationTimer;
base::Timer _updateOuterRippleTimer;
rpl::event_stream<bool> _startOutgoingRequests;
};
} // namespace Calls