Use LargeVideo in the default mode.

This commit is contained in:
John Preston 2021-05-11 15:07:16 +04:00
parent 5f4903a279
commit 0db0abe608
5 changed files with 58 additions and 105 deletions

View file

@ -1191,14 +1191,14 @@ groupCallLargeVideoWide: GroupCallLargeVideo {
controlsAlign: align(top);
namePosition: point(15px, 8px);
statusPosition: point(15px, 28px);
pinPosition: point(52px, 15px);
iconPosition: point(14px, 15px);
pinPosition: point(52px, 16px);
iconPosition: point(14px, 16px);
}
groupCallLargeVideoNarrow: GroupCallLargeVideo {
shadowHeight: 80px;
controlsAlign: align(top);
controlsAlign: align(bottom);
namePosition: point(64px, 44px);
statusPosition: point(64px, 20px);
statusPosition: point(64px, 25px);
pinPosition: point(20px, 12px);
iconPosition: point(18px, 12px);
}

View file

@ -51,6 +51,10 @@ rpl::producer<bool> LargeVideo::pinToggled() const {
return _pinButton.clicks() | rpl::map([=] { return !_pinned; });
}
rpl::producer<QSize> LargeVideo::trackSizeValue() const {
return _trackSize.value();
}
void LargeVideo::setup(
rpl::producer<LargeVideoTrack> track,
rpl::producer<bool> pinned) {
@ -68,6 +72,7 @@ void LargeVideo::setup(
_trackLifetime.destroy();
if (!track.track) {
_trackSize = QSize();
return;
}
track.track->renderNextFrame(
@ -75,6 +80,8 @@ void LargeVideo::setup(
const auto size = track.track->frameSize();
if (size.isEmpty()) {
track.track->markFrameShown();
} else {
_trackSize = size;
}
_content.update();
}, _trackLifetime);
@ -249,20 +256,20 @@ void LargeVideo::paintControls(Painter &p, QRect clip) {
const auto iconLeft = width - _st.iconPosition.x() - icon.width();
const auto iconTop = _topControls
? _st.iconPosition.y()
: (height - _st.iconPosition.y());
: (height - _st.iconPosition.y() - icon.height());
_track.row->paintMuteIcon(
p,
{ iconLeft, iconTop, icon.width(), icon.height() },
MembersRowStyle::LargeVideo);
// Pin.
const auto pinWidth = st::groupCallLargeVideoPin.icon.width();
const auto &pin = st::groupCallLargeVideoPin.icon;
const auto pinLeft = _topControls
? (width - _st.pinPosition.x() - pinWidth)
? (width - _st.pinPosition.x() - pin.width())
: _st.pinPosition.x();
const auto pinTop = _topControls
? _st.pinPosition.y()
: (height - _st.pinPosition.y());
: (height - _st.pinPosition.y() - pin.height());
_pin.paint(p, pinLeft, pinTop, _pinned ? 1. : 0.);
}

View file

@ -63,6 +63,7 @@ public:
void setGeometry(int x, int y, int width, int height);
[[nodiscard]] rpl::producer<bool> pinToggled() const;
[[nodiscard]] rpl::producer<QSize> trackSizeValue() const;
[[nodiscard]] rpl::lifetime &lifetime() {
return _content.lifetime();
@ -109,6 +110,7 @@ private:
bool _topControls = false;
bool _pinned = false;
bool _controlsShown = true;
rpl::variable<QSize> _trackSize;
rpl::lifetime _trackLifetime;
};

View file

@ -1457,7 +1457,19 @@ Members::Members(
, _listController(std::make_unique<Controller>(call, parent))
, _layout(_scroll->setOwnedWidget(
object_ptr<Ui::VerticalLayout>(_scroll.data())))
, _pinnedVideo(_layout->add(object_ptr<Ui::RpWidget>(_layout.get()))) {
, _pinnedVideoWrap(_layout->add(object_ptr<Ui::RpWidget>(_layout.get())))
, _pinnedVideo(
std::make_unique<LargeVideo>(
_pinnedVideoWrap.get(),
st::groupCallLargeVideoNarrow,
true,
_call->videoLargeTrackValue(
) | rpl::map([=](GroupCall::LargeTrack track) {
const auto row = track ? lookupRow(track.peer) : nullptr;
Assert(!track || row != nullptr);
return LargeVideoTrack{ row ? track.track : nullptr, row };
}),
_call->videoEndpointPinnedValue())) {
setupAddMember(call);
setupList();
setupPinnedVideo();
@ -1485,7 +1497,7 @@ auto Members::kickParticipantRequests() const
int Members::desiredHeight() const {
const auto addMember = _addMemberButton.current();
const auto top = _pinnedVideo->height()
const auto top = _pinnedVideoWrap->height()
+ (addMember ? addMember->height() : 0);
const auto count = [&] {
if (const auto real = _call->lookupReal()) {
@ -1602,6 +1614,7 @@ void Members::setMode(PanelMode mode) {
return;
}
_mode = mode;
_pinnedVideo->setVisible(mode == PanelMode::Default);
_list->setMode((mode == PanelMode::Wide)
? PeerListContent::Mode::Custom
: PeerListContent::Mode::Default);
@ -1635,6 +1648,15 @@ void Members::setupList() {
void Members::setupPinnedVideo() {
using namespace rpl::mappers;
_pinnedVideo->pinToggled(
) | rpl::start_with_next([=](bool pinned) {
if (!pinned) {
_call->pinVideoEndpoint(VideoEndpoint{});
} else if (const auto &large = _call->videoEndpointLarge()) {
_call->pinVideoEndpoint(large);
}
}, _pinnedVideo->lifetime());
// New video was pinned or mode changed.
rpl::merge(
_mode.changes() | rpl::filter(
@ -1646,102 +1668,22 @@ void Members::setupPinnedVideo() {
}, _scroll->lifetime());
rpl::combine(
_mode.value(),
_call->videoLargeTrackValue()
) | rpl::map([](PanelMode mode, GroupCall::LargeTrack track) {
return (mode == PanelMode::Default) ? track.track : nullptr;
}) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](Webrtc::VideoTrack *track) {
_pinnedTrackLifetime.destroy();
if (!track) {
_pinnedVideo->resize(_pinnedVideo->width(), 0);
_layout->widthValue(),
_pinnedVideo->trackSizeValue()
) | rpl::start_with_next([=](int width, QSize size) {
if (size.isEmpty() || !width) {
_pinnedVideoWrap->resize(width, 0);
return;
}
const auto frameSize = _pinnedTrackLifetime.make_state<QSize>();
const auto applyFrameSize = [=](QSize size) {
const auto width = _pinnedVideo->width();
if (size.isEmpty() || !width) {
return;
}
const auto heightMin = (width * 9) / 16;
const auto heightMax = (width * 3) / 4;
const auto scaled = size.scaled(
QSize(width, heightMax),
Qt::KeepAspectRatio);
_pinnedVideo->resize(
width,
std::max(scaled.height(), heightMin));
};
track->renderNextFrame(
) | rpl::start_with_next([=] {
const auto size = track->frameSize();
if (size.isEmpty()) {
track->markFrameShown();
} else {
if (*frameSize != size) {
*frameSize = size;
applyFrameSize(size);
}
_pinnedVideo->update();
}
}, _pinnedTrackLifetime);
_layout->widthValue(
) | rpl::start_with_next([=] {
applyFrameSize(track->frameSize());
}, _pinnedTrackLifetime);
_pinnedVideo->paintRequest(
) | rpl::start_with_next([=] {
const auto [image, rotation]
= track->frameOriginalWithRotation();
if (image.isNull()) {
return;
}
auto p = QPainter(_pinnedVideo);
auto hq = PainterHighQualityEnabler(p);
using namespace Media::View;
const auto size = _pinnedVideo->size();
const auto scaled = FlipSizeByRotation(
image.size(),
rotation
).scaled(size, Qt::KeepAspectRatio);
const auto left = (size.width() - scaled.width()) / 2;
const auto top = (size.height() - scaled.height()) / 2;
const auto target = QRect(QPoint(left, top), scaled);
if (UsePainterRotation(rotation)) {
if (rotation) {
p.save();
p.rotate(rotation);
}
p.drawImage(RotatedRect(target, rotation), image);
if (rotation) {
p.restore();
}
} else if (rotation) {
p.drawImage(target, RotateFrameImage(image, rotation));
} else {
p.drawImage(target, image);
}
if (left > 0) {
p.fillRect(0, 0, left, size.height(), Qt::black);
}
if (const auto right = left + scaled.width()
; right < size.width()) {
const auto fill = size.width() - right;
p.fillRect(right, 0, fill, size.height(), Qt::black);
}
if (top > 0) {
p.fillRect(0, 0, size.width(), top, Qt::black);
}
if (const auto bottom = top + scaled.height()
; bottom < size.height()) {
const auto fill = size.height() - bottom;
p.fillRect(0, bottom, size.width(), fill, Qt::black);
}
track->markFrameShown();
}, _pinnedTrackLifetime);
}, lifetime());
const auto heightMin = (width * 9) / 16;
const auto heightMax = (width * 3) / 4;
const auto scaled = size.scaled(
QSize(width, heightMax),
Qt::KeepAspectRatio);
const auto height = std::max(scaled.height(), heightMin);
_pinnedVideoWrap->resize(width, height);
_pinnedVideo->setGeometry(0, 0, width, height);
}, _pinnedVideo->lifetime());
}
void Members::resizeEvent(QResizeEvent *e) {

View file

@ -26,6 +26,7 @@ class GroupCall;
namespace Calls::Group {
class LargeVideo;
class MembersRow;
struct VolumeRequest;
struct MuteRequest;
@ -91,7 +92,8 @@ private:
object_ptr<Ui::ScrollArea> _scroll;
std::unique_ptr<Controller> _listController;
not_null<Ui::VerticalLayout*> _layout;
const not_null<Ui::RpWidget*> _pinnedVideo;
const not_null<Ui::RpWidget*> _pinnedVideoWrap;
const std::unique_ptr<LargeVideo> _pinnedVideo;
rpl::variable<Ui::RpWidget*> _addMemberButton = nullptr;
ListWidget *_list = nullptr;
rpl::event_stream<> _addMemberRequests;