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; const not_null<UserData*> _user;
MTP::Sender _api; MTP::Sender _api;
Type _type = Type::Outgoing; Type _type = Type::Outgoing;
rpl::variable<State> _state = State::WaitingUserConfirmation; rpl::variable<State> _state = State::Starting;
rpl::variable<RemoteAudioState> _remoteAudioState = rpl::variable<RemoteAudioState> _remoteAudioState =
RemoteAudioState::Active; RemoteAudioState::Active;
rpl::variable<Webrtc::VideoState> _remoteVideoState; 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) { void Instance::createCall(
auto call = std::make_unique<Call>(_delegate.get(), user, type, video); not_null<UserData*> user,
const auto raw = call.get(); 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( user->session().account().sessionChanges(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
destroyCall(raw); destroyCall(raw);
}, raw->lifetime()); }, raw->lifetime());
if (_currentCall) { if (_currentCall) {
_currentCallPanel->replaceCall(raw); _currentCallPanel->replaceCall(raw);
std::swap(_currentCall, call); std::swap(_currentCall, call);
call->hangup(); call->hangup();
} else { } else {
_currentCallPanel = std::make_unique<Panel>(raw); _currentCallPanel = std::make_unique<Panel>(raw);
_currentCall = std::move(call); _currentCall = std::move(call);
} }
_currentCallPanel->startOutgoingRequests( if (raw->state() == Call::State::WaitingUserConfirmation) {
) | rpl::start_with_next([=](bool video) { _currentCallPanel->startOutgoingRequests(
raw->applyUserConfirmation(); ) | rpl::start_with_next([=](bool video) {
raw->toggleCameraSharing(video); repeater.callback(video, true, repeater);
refreshServerConfig(&user->session()); }, raw->lifetime());
refreshDhConfig(); } else {
}, raw->lifetime()); refreshServerConfig(&user->session());
_currentCallChanges.fire_copy(raw); refreshDhConfig();
}
_currentCallChanges.fire_copy(raw);
});
performer.callback(isVideo, false, performer);
} }
void Instance::destroyGroupCall(not_null<GroupCall*> call) { void Instance::destroyGroupCall(not_null<GroupCall*> call) {

View file

@ -113,7 +113,7 @@ private:
not_null<Media::Audio::Track*> ensureSoundLoaded(const QString &key); not_null<Media::Audio::Track*> ensureSoundLoaded(const QString &key);
void playSoundOnce(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 destroyCall(not_null<Call*> call);
void createGroupCall( void createGroupCall(

View file

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

View file

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