mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-22 13:42:51 +02:00
Add pinned video in wide mode.
This commit is contained in:
parent
b15623d435
commit
e12fe974b2
3 changed files with 113 additions and 9 deletions
|
@ -410,7 +410,9 @@ void GroupCall::switchToCamera() {
|
|||
return;
|
||||
}
|
||||
_videoDeviceId = _videoInputId;
|
||||
if (_videoOutgoing)
|
||||
if (_videoOutgoing->state() != Webrtc::VideoState::Active) {
|
||||
_videoOutgoing->setState(Webrtc::VideoState::Active);
|
||||
}
|
||||
_videoCapture->switchToDevice(_videoDeviceId.toStdString());
|
||||
}
|
||||
|
||||
|
@ -419,6 +421,9 @@ void GroupCall::switchToScreenSharing(const QString &uniqueId) {
|
|||
return;
|
||||
}
|
||||
_videoDeviceId = uniqueId;
|
||||
if (_videoOutgoing->state() != Webrtc::VideoState::Active) {
|
||||
_videoOutgoing->setState(Webrtc::VideoState::Active);
|
||||
}
|
||||
_videoCapture->switchToDevice(_videoDeviceId.toStdString());
|
||||
}
|
||||
|
||||
|
@ -1432,15 +1437,15 @@ void GroupCall::setupOutgoingVideo() {
|
|||
}
|
||||
_videoOutgoing->stateValue(
|
||||
) | rpl::start_with_next([=](Webrtc::VideoState state) {
|
||||
if (state != Webrtc::VideoState::Inactive && !hasDevices()) {
|
||||
//if (state != Webrtc::VideoState::Inactive && !hasDevices()) {
|
||||
//_errors.fire({ ErrorType::NoCamera }); // #TODO videochats
|
||||
_videoOutgoing->setState(Webrtc::VideoState::Inactive);
|
||||
//_videoOutgoing->setState(Webrtc::VideoState::Inactive);
|
||||
//} else if (state != Webrtc::VideoState::Inactive
|
||||
// && _instance
|
||||
// && !_instance->supportsVideo()) {
|
||||
// _errors.fire({ ErrorType::NotVideoCall });
|
||||
// _videoOutgoing->setState(Webrtc::VideoState::Inactive);
|
||||
} else if (state != Webrtc::VideoState::Inactive) {
|
||||
/*} else */if (state != Webrtc::VideoState::Inactive) {
|
||||
// Paused not supported right now.
|
||||
Assert(state == Webrtc::VideoState::Active);
|
||||
if (!_videoCapture) {
|
||||
|
|
|
@ -47,6 +47,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/timer_rpl.h"
|
||||
#include "app.h"
|
||||
#include "apiwrap.h" // api().kickParticipant.
|
||||
#include "media/view/media_view_pip.h"
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
|
@ -904,6 +906,91 @@ void Panel::setupMembers() {
|
|||
addMembers();
|
||||
}
|
||||
}, _callLifetime);
|
||||
|
||||
setupPinnedVideo();
|
||||
}
|
||||
|
||||
void Panel::setupPinnedVideo() {
|
||||
_pinnedVideo.create(widget());
|
||||
_pinnedVideo->setVisible(_mode == PanelMode::Wide);
|
||||
|
||||
rpl::combine(
|
||||
_pinnedVideo->shownValue(),
|
||||
_call->videoLargeTrackValue()
|
||||
) | rpl::map([](bool shown, Webrtc::VideoTrack *track) {
|
||||
return shown ? track : nullptr;
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=](Webrtc::VideoTrack *track) {
|
||||
_pinnedTrackLifetime.destroy();
|
||||
if (!track) {
|
||||
_pinnedVideo->paintRequest(
|
||||
) | rpl::start_with_next([=](QRect clip) {
|
||||
QPainter(_pinnedVideo.data()).fillRect(clip, Qt::black);
|
||||
}, _pinnedTrackLifetime);
|
||||
_pinnedVideo->update();
|
||||
return;
|
||||
}
|
||||
track->renderNextFrame(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto size = track->frameSize();
|
||||
if (size.isEmpty()) {
|
||||
track->markFrameShown();
|
||||
} else {
|
||||
_pinnedVideo->update();
|
||||
}
|
||||
}, _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);
|
||||
}, widget()->lifetime());
|
||||
}
|
||||
|
||||
void Panel::setupJoinAsChangedToasts() {
|
||||
|
@ -1402,6 +1489,7 @@ bool Panel::updateMode() {
|
|||
if (_members) {
|
||||
_members->setMode(mode);
|
||||
}
|
||||
_pinnedVideo->setVisible(mode == PanelMode::Wide);
|
||||
updateControlsGeometry();
|
||||
return true;
|
||||
}
|
||||
|
@ -1457,18 +1545,25 @@ void Panel::updateMembersGeometry() {
|
|||
return;
|
||||
}
|
||||
const auto desiredHeight = _members->desiredHeight();
|
||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||
const auto membersTop = st::groupCallMembersTop;
|
||||
const auto availableHeight = muteTop
|
||||
- membersTop
|
||||
- st::groupCallMembersMargin.bottom();
|
||||
if (_mode == PanelMode::Wide) {
|
||||
_members->setGeometry(
|
||||
st::groupCallNarrowSkip,
|
||||
0,
|
||||
st::groupCallNarrowSize.width(),
|
||||
std::min(desiredHeight, widget()->height()));
|
||||
const auto pinnedLeft = st::groupCallNarrowSkip * 2
|
||||
+ st::groupCallNarrowSize.width();
|
||||
_pinnedVideo->setGeometry(
|
||||
pinnedLeft,
|
||||
membersTop,
|
||||
widget()->width() - pinnedLeft,
|
||||
availableHeight);
|
||||
} else {
|
||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||
const auto membersTop = st::groupCallMembersTop;
|
||||
const auto availableHeight = muteTop
|
||||
- membersTop
|
||||
- st::groupCallMembersMargin.bottom();
|
||||
const auto membersWidthAvailable = widget()->width()
|
||||
- st::groupCallMembersMargin.left()
|
||||
- st::groupCallMembersMargin.right();
|
||||
|
|
|
@ -31,6 +31,7 @@ class CallButton;
|
|||
class CallMuteButton;
|
||||
class IconButton;
|
||||
class FlatLabel;
|
||||
class RpWidget;
|
||||
template <typename Widget>
|
||||
class FadeWrap;
|
||||
template <typename Widget>
|
||||
|
@ -81,6 +82,7 @@ private:
|
|||
void initGeometry();
|
||||
void setupScheduledLabels(rpl::producer<TimeId> date);
|
||||
void setupMembers();
|
||||
void setupPinnedVideo();
|
||||
void setupJoinAsChangedToasts();
|
||||
void setupTitleChangedToasts();
|
||||
void setupAllowedToSpeakToasts();
|
||||
|
@ -135,6 +137,8 @@ private:
|
|||
object_ptr<Ui::DropdownMenu> _menu = { nullptr };
|
||||
object_ptr<Ui::AbstractButton> _joinAsToggle = { nullptr };
|
||||
object_ptr<Members> _members = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _pinnedVideo = { nullptr };
|
||||
rpl::lifetime _pinnedTrackLifetime;
|
||||
object_ptr<Ui::FlatLabel> _startsIn = { nullptr };
|
||||
object_ptr<Ui::RpWidget> _countdown = { nullptr };
|
||||
std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;
|
||||
|
|
Loading…
Add table
Reference in a new issue