From f18e157e4692587d34267ebe44a19fc115681c5e Mon Sep 17 00:00:00 2001 From: John Preston <johnprestonmail@gmail.com> Date: Tue, 15 Jun 2021 12:33:21 +0400 Subject: [PATCH] Add video placeholder if can't receive it. --- Telegram/Resources/langs/lang.strings | 2 + Telegram/SourceFiles/calls/calls.style | 3 + .../calls/group/calls_group_call.cpp | 82 +++++++---- .../calls/group/calls_group_call.h | 12 +- .../calls/group/calls_group_members.cpp | 130 +++++++++++++++++- .../calls/group/calls_group_members.h | 1 + .../calls/group/calls_group_panel.cpp | 1 + .../calls/group/calls_group_viewport.cpp | 14 +- .../calls/group/calls_group_viewport.h | 6 +- .../group/calls_group_viewport_opengl.cpp | 30 ++-- .../calls/group/calls_group_viewport_tile.cpp | 18 +-- .../calls/group/calls_group_viewport_tile.h | 1 + Telegram/SourceFiles/core/application.cpp | 8 +- .../media/view/media_view_overlay_widget.cpp | 1 - .../media/view/media_view_pip_opengl.cpp | 17 +-- Telegram/ThirdParty/tgcalls | 2 +- 16 files changed, 249 insertions(+), 79 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3b2170c77..30ccd0944 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2058,6 +2058,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_ptt_delay" = "Push to Talk release delay: {delay}"; "lng_group_call_share" = "Share Invite Link"; "lng_group_call_noise_suppression" = "Enable Noise Suppression"; +"lng_group_call_limit#one" = "Video is only available\nfor the first {count} member"; +"lng_group_call_limit#other" = "Video is only available\nfor the first {count} members"; "lng_group_call_share_speaker" = "Users with this link can speak"; "lng_group_call_copy_speaker_link" = "Copy Speaker Link"; "lng_group_call_copy_listener_link" = "Copy Listener Link"; diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 288610e65..ddcea65fc 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -1229,6 +1229,9 @@ groupCallVideoTile: GroupCallVideoTile { groupCallVideoSmallSkip: 4px; groupCallVideoLargeSkip: 6px; +groupCallVideoPlaceholderHeight: 212px; +groupCallVideoPlaceholderIconTop: 50px; +groupCallVideoPlaceholderTextTop: 120px; groupCallTooltip: Tooltip(defaultTooltip) { textBg: groupCallMembersBg; diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index dfb86b422..cd40c9202 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -821,6 +821,9 @@ void GroupCall::setState(State state) { if (const auto call = _peer->groupCall(); call && call->id() == _id) { call->setInCall(); } + if (!videoIsWorking()) { + refreshHasNotShownVideo(); + } } if (false @@ -1043,6 +1046,9 @@ void GroupCall::markEndpointActive( bool paused) { if (!endpoint) { return; + } else if (active && !videoIsWorking()) { + refreshHasNotShownVideo(); + return; } const auto i = _activeVideoTracks.find(endpoint); const auto changed = active @@ -1067,26 +1073,34 @@ void GroupCall::markEndpointActive( .peer = endpoint.peer, }).first; const auto track = i->second.track.get(); - if (!track->frameSize().isEmpty() - || track->state() == Webrtc::VideoState::Paused) { + + track->renderNextFrame( + ) | rpl::start_with_next([=] { + auto &activeTrack = _activeVideoTracks[endpoint]; + const auto size = track->frameSize(); + if (size.isEmpty()) { + track->markFrameShown(); + } else if (!activeTrack.shown) { + activeTrack.shown = true; + markTrackShown(endpoint, true); + } + activeTrack.trackSize = size; + }, i->second.lifetime); + + const auto size = track->frameSize(); + i->second.trackSize = size; + if (!size.isEmpty() || paused) { + i->second.shown = true; shown = true; } else { - auto hasFrame = track->renderNextFrame() | rpl::map([=] { - return !track->frameSize().isEmpty(); - }); - auto isPaused = track->stateValue( - ) | rpl::map([=](Webrtc::VideoState state) { - return (state == Webrtc::VideoState::Paused); - }); - rpl::merge( - std::move(hasFrame), - std::move(isPaused) - ) | rpl::filter([=](bool shouldShow) { - return shouldShow; + track->stateValue( + ) | rpl::filter([=](Webrtc::VideoState state) { + return (state == Webrtc::VideoState::Paused) + && !_activeVideoTracks[endpoint].shown; }) | rpl::start_with_next([=] { - _activeVideoTracks[endpoint].shownTrackingLifetime.destroy(); + _activeVideoTracks[endpoint].shown = true; markTrackShown(endpoint, true); - }, i->second.shownTrackingLifetime); + }, i->second.lifetime); } addVideoOutput(i->first.id, { track->sink() }); } else { @@ -1109,10 +1123,11 @@ void GroupCall::markTrackShown(const VideoEndpoint &endpoint, bool shown) { const auto changed = shown ? _shownVideoTracks.emplace(endpoint).second : _shownVideoTracks.remove(endpoint); - if (changed) { - _videoStreamShownUpdates.fire_copy({ endpoint, shown }); + if (!changed) { + return; } - if (shown && changed && endpoint.type == VideoEndpointType::Screen) { + _videoStreamShownUpdates.fire_copy({ endpoint, shown }); + if (shown && endpoint.type == VideoEndpointType::Screen) { crl::on_main(this, [=] { if (_shownVideoTracks.contains(endpoint)) { pinVideoEndpoint(endpoint); @@ -2431,21 +2446,37 @@ void GroupCall::updateRequestedVideoChannelsDelayed() { }); } +void GroupCall::refreshHasNotShownVideo() { + if (!_joinState.ssrc || hasNotShownVideo()) { + return; + } + const auto real = lookupReal(); + Assert(real != nullptr); + + const auto hasVideo = [&](const Data::GroupCallParticipant &data) { + return (data.peer != _joinAs) + && (!GetCameraEndpoint(data.videoParams).empty() + || !GetScreenEndpoint(data.videoParams).empty()); + }; + _hasNotShownVideo = _joinState.ssrc + && ranges::any_of(real->participants(), hasVideo); +} + void GroupCall::fillActiveVideoEndpoints() { const auto real = lookupReal(); Assert(real != nullptr); - if (const auto participant = real->participantByPeer(_joinAs)) { - _videoIsWorking = participant->videoJoined; + const auto me = real->participantByPeer(_joinAs); + if (me && me->videoJoined) { + _videoIsWorking = true; + _hasNotShownVideo = false; } else { + refreshHasNotShownVideo(); _videoIsWorking = false; - } - if (!videoIsWorking()) { toggleVideo(false); toggleScreenSharing(std::nullopt); } - const auto &participants = real->participants(); const auto &large = _videoEndpointLarge.current(); auto largeFound = false; auto endpoints = _activeVideoTracks | ranges::views::transform([]( @@ -2469,7 +2500,7 @@ void GroupCall::fillActiveVideoEndpoints() { }; using Type = VideoEndpointType; if (_videoIsWorking.current()) { - for (const auto &participant : participants) { + for (const auto &participant : real->participants()) { const auto camera = GetCameraEndpoint(participant.videoParams); if (camera != _cameraEndpoint && camera != _screenEndpoint @@ -2485,7 +2516,6 @@ void GroupCall::fillActiveVideoEndpoints() { feedOne({ Type::Screen, participant.peer, screen }, paused); } } - const auto pausedState = Webrtc::VideoState::Paused; feedOne( { Type::Camera, _joinAs, cameraSharingEndpoint() }, isCameraPaused()); diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 2d66d25f4..e6bcae38e 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -324,9 +324,11 @@ public: struct VideoTrack { std::unique_ptr<Webrtc::VideoTrack> track; + rpl::variable<QSize> trackSize; PeerData *peer = nullptr; - rpl::lifetime shownTrackingLifetime; + rpl::lifetime lifetime; Group::VideoQuality quality = Group::VideoQuality(); + bool shown = false; [[nodiscard]] explicit operator bool() const { return (track != nullptr); @@ -366,6 +368,12 @@ public: [[nodiscard]] rpl::producer<bool> videoIsWorkingValue() const { return _videoIsWorking.value(); } + [[nodiscard]] bool hasNotShownVideo() const { + return _hasNotShownVideo.current(); + } + [[nodiscard]] rpl::producer<bool> hasNotShownVideoValue() const { + return _hasNotShownVideo.value(); + } void setCurrentAudioDevice(bool input, const QString &deviceId); void setCurrentVideoDevice(const QString &deviceId); @@ -514,6 +522,7 @@ private: void updateRequestedVideoChannels(); void updateRequestedVideoChannelsDelayed(); void fillActiveVideoEndpoints(); + void refreshHasNotShownVideo(); void editParticipant( not_null<PeerData*> participantPeer, @@ -570,6 +579,7 @@ private: rpl::variable<MuteState> _muted = MuteState::Muted; rpl::variable<bool> _canManage = false; rpl::variable<bool> _videoIsWorking = false; + rpl::variable<bool> _hasNotShownVideo = false; bool _initialMuteStateSent = false; bool _acceptFields = false; diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index f3e4b3e80..c5a2ea3fb 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -29,6 +29,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/application.h" // Core::App().domain, .activeWindow. #include "main/main_domain.h" // Core::App().domain().activate. #include "main/main_session.h" +#include "main/main_account.h" // account().appConfig(). +#include "main/main_app_config.h" // appConfig().get<double>(). #include "boxes/peers/edit_participants_box.h" // SubscribeToMigration. #include "window/window_controller.h" // Controller::sessionController. #include "window/window_session_controller.h" @@ -41,9 +43,110 @@ namespace { constexpr auto kKeepRaisedHandStatusDuration = 3 * crl::time(1000); constexpr auto kShadowMaxAlpha = 74; +constexpr auto kUserpicSizeForBlur = 40; +constexpr auto kUserpicBlurRadius = 8; using Row = MembersRow; +void SetupVideoPlaceholder( + not_null<Ui::RpWidget*> widget, + not_null<PeerData*> chat) { + struct State { + QImage blurred; + QImage rounded; + InMemoryKey key = {}; + std::shared_ptr<Data::CloudImageView> view; + qint64 blurredCacheKey = 0; + }; + const auto state = widget->lifetime().make_state<State>(); + const auto refreshBlurred = [=] { + const auto key = chat->userpicUniqueKey(state->view); + if (state->key == key && !state->blurred.isNull()) { + return; + } + constexpr auto size = kUserpicSizeForBlur; + state->key = key; + state->blurred = QImage( + QSize(size, size), + QImage::Format_ARGB32_Premultiplied); + { + auto p = Painter(&state->blurred); + auto hq = PainterHighQualityEnabler(p); + chat->paintUserpicSquare(p, state->view, 0, 0, size); + } + state->blurred = Images::BlurLargeImage( + std::move(state->blurred), + kUserpicBlurRadius); + widget->update(); + }; + const auto refreshRounded = [=](QSize size) { + refreshBlurred(); + const auto key = state->blurred.cacheKey(); + if (state->rounded.size() == size && state->blurredCacheKey == key) { + return; + } + state->blurredCacheKey = key; + state->rounded = Images::prepare( + state->blurred, + size.width(), + size.width(), // Square + Images::Option::Smooth, + size.width(), + size.height()); + { + auto p = QPainter(&state->rounded); + p.fillRect( + 0, + 0, + size.width(), + size.height(), + QColor(0, 0, 0, Viewport::kShadowMaxAlpha)); + } + state->rounded = Images::prepare( + std::move(state->rounded), + size.width(), + size.height(), + (Images::Option::RoundedLarge | Images::Option::RoundedAll), + size.width(), + size.height()); + }; + chat->loadUserpic(); + refreshBlurred(); + + widget->paintRequest( + ) | rpl::start_with_next([=] { + const auto size = QSize( + widget->width(), + widget->height() - st::groupCallVideoSmallSkip); + refreshRounded(size * cIntRetinaFactor()); + + auto p = QPainter(widget); + const auto inner = QRect(QPoint(), size); + p.drawImage(inner, state->rounded); + st::groupCallPaused.paint( + p, + (size.width() - st::groupCallPaused.width()) / 2, + st::groupCallVideoPlaceholderIconTop, + size.width()); + + const auto skip = st::groupCallVideoLargeSkip; + const auto limit = chat->session().account().appConfig().get<double>( + "groupcall_video_participants_max", + 30.); + p.setPen(st::groupCallVideoTextFg); + const auto text = QRect( + skip, + st::groupCallVideoPlaceholderTextTop, + (size.width() - 2 * skip), + size.height() - st::groupCallVideoPlaceholderTextTop); + p.setFont(st::semiboldFont); + p.drawText( + text, + tr::lng_group_call_limit(tr::now, lt_count, int(limit)), + style::al_top); + }, widget->lifetime()); +} + } // namespace class Members::Controller final @@ -1467,6 +1570,7 @@ Members::Members( , _layout(_scroll->setOwnedWidget( object_ptr<Ui::VerticalLayout>(_scroll.data()))) , _videoWrap(_layout->add(object_ptr<Ui::RpWidget>(_layout.get()))) +, _videoPlaceholder(std::make_unique<Ui::RpWidget>(_videoWrap.get())) , _viewport( std::make_unique<Viewport>( _videoWrap.get(), @@ -1704,11 +1808,27 @@ void Members::trackViewportGeometry() { _scroll->scrollTopValue( ) | rpl::skip(1) | rpl::start_with_next(move, _viewport->lifetime()); - _viewport->fullHeightValue( - ) | rpl::start_with_next([=](int height) { - _videoWrap->resize(_videoWrap->width(), height); - move(); - resize(); + rpl::combine( + _layout->widthValue(), + _call->hasNotShownVideoValue() + ) | rpl::start_with_next([=](int width, bool has) { + const auto height = has ? st::groupCallVideoPlaceholderHeight : 0; + _videoPlaceholder->setGeometry(0, 0, width, height); + }, _videoPlaceholder->lifetime()); + + SetupVideoPlaceholder(_videoPlaceholder.get(), _call->peer()); + + rpl::combine( + _videoPlaceholder->heightValue(), + _viewport->fullHeightValue() + ) | rpl::start_with_next([=](int placeholder, int viewport) { + _videoWrap->resize( + _videoWrap->width(), + std::max(placeholder, viewport)); + if (viewport > 0) { + move(); + resize(); + } }, _viewport->lifetime()); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.h b/Telegram/SourceFiles/calls/group/calls_group_members.h index f828d7910..198fdcaad 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.h +++ b/Telegram/SourceFiles/calls/group/calls_group_members.h @@ -101,6 +101,7 @@ private: std::unique_ptr<Controller> _listController; not_null<Ui::VerticalLayout*> _layout; const not_null<Ui::RpWidget*> _videoWrap; + const std::unique_ptr<Ui::RpWidget> _videoPlaceholder; std::unique_ptr<Viewport> _viewport; rpl::variable<Ui::RpWidget*> _addMemberButton = nullptr; RpWidget *_topSkip = nullptr; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index a43acc24b..03b46c3e8 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -854,6 +854,7 @@ void Panel::setupVideo(not_null<Viewport*> viewport) { viewport->add( endpoint, VideoTileTrack{ track.track.get(), row }, + track.trackSize.value(), std::move(pinned)); }; for (const auto &[endpoint, track] : _call->activeVideoTracks()) { diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp index 7abe2cb20..497b7d978 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport.cpp @@ -225,10 +225,12 @@ void Viewport::setControlsShown(float64 shown) { void Viewport::add( const VideoEndpoint &endpoint, VideoTileTrack track, + rpl::producer<QSize> trackSize, rpl::producer<bool> pinned) { _tiles.push_back(std::make_unique<VideoTile>( endpoint, track, + std::move(trackSize), std::move(pinned), [=] { widget()->update(); })); @@ -711,11 +713,13 @@ void Viewport::updateTilesGeometryColumn(int outerWidth) { const auto layoutNext = [&](not_null<VideoTile*> tile) { const auto size = tile->trackOrUserpicSize(); const auto shown = !size.isEmpty() && _large && tile != _large; - const auto height = shown - ? st::groupCallNarrowVideoHeight - : 0; - setTileGeometry(tile, { 0, y + top, outerWidth, height }); - top += height ? (height + st::groupCallVideoSmallSkip) : 0; + const auto height = st::groupCallNarrowVideoHeight; + if (!shown) { + tile->hide(); + } else { + setTileGeometry(tile, { 0, y + top, outerWidth, height }); + top += height + st::groupCallVideoSmallSkip; + } }; const auto topPeer = _large ? _large->row()->peer().get() : nullptr; const auto reorderNeeded = [&] { diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport.h b/Telegram/SourceFiles/calls/group/calls_group_viewport.h index b7c8c8080..a26e0a811 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport.h +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport.h @@ -39,6 +39,7 @@ enum class VideoQuality; struct VideoTileTrack { Webrtc::VideoTrack *track = nullptr; MembersRow *row = nullptr; + rpl::variable<QSize> trackSize; [[nodiscard]] explicit operator bool() const { return track != nullptr; @@ -77,6 +78,7 @@ public: void add( const VideoEndpoint &endpoint, VideoTileTrack track, + rpl::producer<QSize> trackSize, rpl::producer<bool> pinned); void remove(const VideoEndpoint &endpoint); void showLarge(const VideoEndpoint &endpoint); @@ -91,6 +93,8 @@ public: [[nodiscard]] rpl::lifetime &lifetime(); + static constexpr auto kShadowMaxAlpha = 80; + private: struct Textures; class VideoTile; @@ -132,8 +136,6 @@ private: } }; - static constexpr auto kShadowMaxAlpha = 80; - void setup(); [[nodiscard]] bool wide() const; diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp index 55044f935..e1aec4b91 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport_opengl.cpp @@ -320,7 +320,6 @@ Viewport::RendererGL::RendererGL(not_null<Viewport*> owner) void Viewport::RendererGL::init( not_null<QOpenGLWidget*> widget, QOpenGLFunctions &f) { - _factor = widget->devicePixelRatio(); _frameBuffer.emplace(); _frameBuffer->setUsagePattern(QOpenGLBuffer::DynamicDraw); _frameBuffer->create(); @@ -427,7 +426,11 @@ void Viewport::RendererGL::setDefaultViewport(QOpenGLFunctions &f) { void Viewport::RendererGL::paint( not_null<QOpenGLWidget*> widget, QOpenGLFunctions &f) { - _factor = widget->devicePixelRatio(); + const auto factor = widget->devicePixelRatio(); + if (_factor != factor) { + _factor = factor; + _buttons.invalidate(); + } _viewport = widget->size(); const auto defaultFramebufferObject = widget->defaultFramebufferObject(); @@ -1054,7 +1057,6 @@ void Viewport::RendererGL::ensureButtonsImage() { if (_buttons) { return; } - const auto factor = cIntRetinaFactor(); const auto pinOnSize = VideoTile::PinInnerSize(true); const auto pinOffSize = VideoTile::PinInnerSize(false); const auto backSize = VideoTile::BackInnerSize(); @@ -1074,18 +1076,18 @@ void Viewport::RendererGL::ensureButtonsImage() { + backSize.height() + muteSize.height() + pausedSize.height())); - const auto imageSize = fullSize * factor; + const auto imageSize = fullSize * _factor; auto image = _buttons.takeImage(); if (image.size() != imageSize) { image = QImage(imageSize, QImage::Format_ARGB32_Premultiplied); } image.fill(Qt::transparent); - image.setDevicePixelRatio(cRetinaFactor()); + image.setDevicePixelRatio(_factor); { auto p = Painter(&image); auto hq = PainterHighQualityEnabler(p); - _pinOn = QRect(QPoint(), pinOnSize * factor); + _pinOn = QRect(QPoint(), pinOnSize * _factor); VideoTile::PaintPinButton( p, true, @@ -1096,7 +1098,9 @@ void Viewport::RendererGL::ensureButtonsImage() { &_pinIcon); const auto pinOffTop = pinOnSize.height(); - _pinOff = QRect(QPoint(0, pinOffTop) * factor, pinOffSize * factor); + _pinOff = QRect( + QPoint(0, pinOffTop) * _factor, + pinOffSize * _factor); VideoTile::PaintPinButton( p, false, @@ -1107,7 +1111,7 @@ void Viewport::RendererGL::ensureButtonsImage() { &_pinIcon); const auto backTop = pinOffTop + pinOffSize.height(); - _back = QRect(QPoint(0, backTop) * factor, backSize * factor); + _back = QRect(QPoint(0, backTop) * _factor, backSize * _factor); VideoTile::PaintBackButton( p, 0, @@ -1116,16 +1120,18 @@ void Viewport::RendererGL::ensureButtonsImage() { &_pinBackground); const auto muteTop = backTop + backSize.height(); - _muteOn = QRect(QPoint(0, muteTop) * factor, muteSize * factor); + _muteOn = QRect(QPoint(0, muteTop) * _factor, muteSize * _factor); _muteIcon.paint(p, { 0, muteTop }, 1.); _muteOff = QRect( - QPoint(muteSize.width(), muteTop) * factor, - muteSize * factor); + QPoint(muteSize.width(), muteTop) * _factor, + muteSize * _factor); _muteIcon.paint(p, { muteSize.width(), muteTop }, 0.); const auto pausedTop = muteTop + muteSize.height(); - _paused = QRect(QPoint(0, pausedTop) * factor, pausedSize * factor); + _paused = QRect( + QPoint(0, pausedTop) * _factor, + pausedSize * _factor); st::groupCallPaused.paint(p, 0, pausedTop, fullSize.width()); } _buttons.setImage(std::move(image)); diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.cpp b/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.cpp index 46e61d79f..ccb5d33bc 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.cpp @@ -25,11 +25,13 @@ constexpr auto kPausedVideoSize = 90; Viewport::VideoTile::VideoTile( const VideoEndpoint &endpoint, VideoTileTrack track, + rpl::producer<QSize> trackSize, rpl::producer<bool> pinned, Fn<void()> update) : _endpoint(endpoint) , _update(std::move(update)) -, _track(track) { +, _track(track) +, _trackSize(std::move(trackSize)) { Expects(track.track != nullptr); Expects(track.row != nullptr); @@ -254,19 +256,7 @@ void Viewport::VideoTile::setup(rpl::producer<bool> pinned) { }, _lifetime); _track.track->renderNextFrame( - ) | rpl::start_with_next([=] { - const auto size = _track.track->frameSize(); - if (size.isEmpty()) { - _track.track->markFrameShown(); - } else { - _trackSize = size; - } - _update(); - }, _lifetime); - - if (const auto size = _track.track->frameSize(); !size.isEmpty()) { - _trackSize = size; - } + ) | rpl::start_with_next(_update, _lifetime); updateTopControlsSize(); } diff --git a/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.h b/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.h index 0b0080f0e..5b05f6797 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.h +++ b/Telegram/SourceFiles/calls/group/calls_group_viewport_tile.h @@ -26,6 +26,7 @@ public: VideoTile( const VideoEndpoint &endpoint, VideoTileTrack track, + rpl::producer<QSize> trackSize, rpl::producer<bool> pinned, Fn<void()> update); diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index d6cf194dc..7577ede6d 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -304,10 +304,10 @@ void Application::showOpenGLCrashNotification() { Local::writeSettings(); }; _window->show(Box<ConfirmBox>( - "Last time OpenGL crashed on initialization. " - "Perhaps it is a problem with your graphics card driver.\n\n" - "Right now OpenGL was disabled. You can try to enable it back " - "or keep it disabled, if it continues crashing.", + "There may be a problem with your graphics drivers and OpenGL. " + "Try updating your drivers.\n\n" + "OpenGL has been disabled. You can try to enable it again " + "or keep it disabled if crashes continue.", "Enable", "Keep Disabled", enable, diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 252690e59..db7e50645 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -3274,7 +3274,6 @@ void OverlayWidget::paint(not_null<Renderer*> renderer) { } paintRadialLoading(renderer); } else { - int a = 0; if (_themePreviewShown) { renderer->paintThemePreview(_themePreviewRect); } else if (documentBubbleShown() && !_docRect.isEmpty()) { diff --git a/Telegram/SourceFiles/media/view/media_view_pip_opengl.cpp b/Telegram/SourceFiles/media/view/media_view_pip_opengl.cpp index f027bb9f0..c295df385 100644 --- a/Telegram/SourceFiles/media/view/media_view_pip_opengl.cpp +++ b/Telegram/SourceFiles/media/view/media_view_pip_opengl.cpp @@ -406,21 +406,22 @@ void Pip::RendererGL::paintTransformedContent( _f->glActiveTexture(rgbaFrame ? GL_TEXTURE1 : GL_TEXTURE3); _shadowImage.bind(*_f); + const auto globalFactor = cIntRetinaFactor(); const auto fadeAlpha = st::radialBg->c.alphaF() * geometry.fade; const auto roundRect = transformRect(RoundingRect(geometry)); program->setUniformValue("roundRect", Uniform(roundRect)); program->setUniformValue("h_texture", GLint(rgbaFrame ? 1 : 3)); program->setUniformValue("h_size", QSizeF(_shadowImage.image().size())); program->setUniformValue("h_extend", QVector4D( - st::callShadow.extend.left(), - st::callShadow.extend.top(), - st::callShadow.extend.right(), - st::callShadow.extend.bottom())); + st::callShadow.extend.left() * globalFactor, + st::callShadow.extend.top() * globalFactor, + st::callShadow.extend.right() * globalFactor, + st::callShadow.extend.bottom() * globalFactor)); program->setUniformValue("h_components", QVector4D( - float(st::callShadow.topLeft.width()), - float(st::callShadow.topLeft.height()), - float(st::callShadow.left.width()), - float(st::callShadow.top.height()))); + float(st::callShadow.topLeft.width() * globalFactor), + float(st::callShadow.topLeft.height() * globalFactor), + float(st::callShadow.left.width() * globalFactor), + float(st::callShadow.top.height() * globalFactor))); program->setUniformValue( "roundRadius", GLfloat(st::roundRadiusLarge * _factor)); diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 9adb220f7..d147f286c 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 9adb220f798cadc0848d3e1efbf32fb2a98a3bcb +Subproject commit d147f286cfe2a23c49c438a63be9aa1c0a04344b