Show video large on click.

This commit is contained in:
John Preston 2021-05-30 19:14:08 +04:00
parent 97c7c0742c
commit 090d7d7112
6 changed files with 91 additions and 59 deletions

View File

@ -569,7 +569,6 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
using Update = Data::GroupCall::ParticipantUpdate;
real->participantUpdated(
) | rpl::start_with_next([=](const Update &data) {
const auto &pinned = _videoEndpointPinned.current();
const auto regularEndpoint = [&](const std::string &endpoint)
-> const std::string & {
return (endpoint.empty()
@ -906,8 +905,8 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) {
}
addVideoOutput(i->first.id, { track->sink() });
} else {
if (_videoEndpointPinned.current() == endpoint) {
_videoEndpointPinned = VideoEndpoint();
if (_videoEndpointLarge.current() == endpoint) {
setVideoEndpointLarge({});
}
_activeVideoTracks.erase(i);
}
@ -2197,8 +2196,8 @@ void GroupCall::fillActiveVideoEndpoints() {
Assert(real != nullptr);
const auto &participants = real->participants();
const auto &pinned = _videoEndpointPinned.current();
auto pinnedFound = false;
const auto &large = _videoEndpointLarge.current();
auto largeFound = false;
auto endpoints = _activeVideoTracks | ranges::views::transform([](
const auto &pair) {
return pair.first;
@ -2209,8 +2208,8 @@ void GroupCall::fillActiveVideoEndpoints() {
const auto feedOne = [&](VideoEndpoint endpoint) {
if (endpoint.empty()) {
return;
} else if (endpoint == pinned) {
pinnedFound = true;
} else if (endpoint == large) {
largeFound = true;
}
if (!removed.remove(endpoint)) {
markEndpointActive(std::move(endpoint), true);
@ -2233,8 +2232,8 @@ void GroupCall::fillActiveVideoEndpoints() {
}
feedOne({ Type::Camera, _joinAs, cameraSharingEndpoint() });
feedOne({ Type::Screen, _joinAs, screenSharingEndpoint() });
if (pinned && !pinnedFound) {
_videoEndpointPinned = VideoEndpoint();
if (large && !largeFound) {
setVideoEndpointLarge({});
}
for (const auto &endpoint : removed) {
markEndpointActive(endpoint, false);
@ -2544,7 +2543,24 @@ void GroupCall::sendSelfUpdate(SendUpdateType type) {
}
void GroupCall::pinVideoEndpoint(VideoEndpoint endpoint) {
_videoEndpointPinned = endpoint;
_videoEndpointPinned = false;
if (endpoint) {
setVideoEndpointLarge(std::move(endpoint));
_videoEndpointPinned = true;
}
}
void GroupCall::showVideoEndpointLarge(VideoEndpoint endpoint) {
_videoEndpointPinned = false;
setVideoEndpointLarge(std::move(endpoint));
_videoLargeShowTime = crl::now();
}
void GroupCall::setVideoEndpointLarge(VideoEndpoint endpoint) {
if (!endpoint) {
_videoEndpointPinned = false;
}
_videoEndpointLarge = endpoint;
}
void GroupCall::requestVideoQuality(

View File

@ -131,11 +131,6 @@ inline bool operator>=(
return !(a < b);
}
struct VideoPinToggle {
VideoEndpoint endpoint;
bool pinned = false;
};
struct VideoActiveToggle {
VideoEndpoint endpoint;
bool active = false;
@ -301,17 +296,27 @@ public:
-> rpl::producer<VideoActiveToggle> {
return _videoStreamShownUpdates.events();
}
void pinVideoEndpoint(VideoEndpoint endpoint);
void requestVideoQuality(
const VideoEndpoint &endpoint,
Group::VideoQuality quality);
[[nodiscard]] const VideoEndpoint &videoEndpointPinned() const {
[[nodiscard]] bool videoEndpointPinned() const {
return _videoEndpointPinned.current();
}
[[nodiscard]] auto videoEndpointPinnedValue() const
-> rpl::producer<VideoEndpoint> {
[[nodiscard]] rpl::producer<bool> videoEndpointPinnedValue() const {
return _videoEndpointPinned.value();
}
void pinVideoEndpoint(VideoEndpoint endpoint);
void showVideoEndpointLarge(VideoEndpoint endpoint);
[[nodiscard]] const VideoEndpoint &videoEndpointLarge() const {
return _videoEndpointLarge.current();
}
[[nodiscard]] auto videoEndpointLargeValue() const
-> rpl::producer<VideoEndpoint> {
return _videoEndpointLarge.value();
}
struct VideoTrack {
std::unique_ptr<Webrtc::VideoTrack> track;
PeerData *peer = nullptr;
@ -508,6 +513,7 @@ private:
void setScreenEndpoint(std::string endpoint);
void setCameraEndpoint(std::string endpoint);
void addVideoOutput(const std::string &endpoint, SinkPointer sink);
void setVideoEndpointLarge(VideoEndpoint endpoint);
void markEndpointActive(VideoEndpoint endpoint, bool active);
void markTrackShown(const VideoEndpoint &endpoint, bool shown);
@ -584,7 +590,9 @@ private:
rpl::event_stream<VideoActiveToggle> _videoStreamShownUpdates;
base::flat_map<VideoEndpoint, VideoTrack> _activeVideoTracks;
base::flat_set<VideoEndpoint> _shownVideoTracks;
rpl::variable<VideoEndpoint> _videoEndpointPinned;
rpl::variable<VideoEndpoint> _videoEndpointLarge;
rpl::variable<bool> _videoEndpointPinned = false;
crl::time _videoLargeShowTime = 0;
base::flat_map<uint32, Data::LastSpokeTimes> _lastSpoke;
rpl::event_stream<Group::RejoinEvent> _rejoinEvents;
rpl::event_stream<> _allowedToSpeakNotifications;

View File

@ -278,10 +278,10 @@ void Members::Controller::setupListChangeViewers() {
}
}, _lifetime);
_call->videoEndpointPinnedValue(
) | rpl::start_with_next([=](const VideoEndpoint &pinned) {
if (pinned) {
hideRowsWithVideoExcept(pinned);
_call->videoEndpointLargeValue(
) | rpl::start_with_next([=](const VideoEndpoint &large) {
if (large) {
hideRowsWithVideoExcept(large);
} else {
showAllHiddenRows();
}
@ -289,8 +289,8 @@ void Members::Controller::setupListChangeViewers() {
_call->videoStreamShownUpdates(
) | rpl::filter([=](const VideoActiveToggle &update) {
const auto &pinned = _call->videoEndpointPinned();
return pinned && (update.endpoint != pinned);
const auto &large = _call->videoEndpointLarge();
return large && (update.endpoint != large);
}) | rpl::start_with_next([=](const VideoActiveToggle &update) {
if (update.active) {
hideRowWithVideo(update.endpoint);
@ -353,10 +353,10 @@ void Members::Controller::hideRowWithVideo(const VideoEndpoint &endpoint) {
void Members::Controller::showRowWithVideo(const VideoEndpoint &endpoint) {
const auto peer = endpoint.peer;
const auto &pinned = _call->videoEndpointPinned();
if (pinned) {
const auto &large = _call->videoEndpointLarge();
if (large) {
for (const auto &endpoint : _call->shownVideoTracks()) {
if (endpoint != pinned && endpoint.peer == peer) {
if (endpoint != large && endpoint.peer == peer) {
// Still hidden with another video.
return;
}
@ -1189,11 +1189,12 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
if (const auto real = _call->lookupReal()) {
const auto participant = real->participantByPeer(participantPeer);
if (participant) {
const auto &pinned = _call->videoEndpointPinned();
const auto &large = _call->videoEndpointLarge();
const auto pinned = _call->videoEndpointPinned();
const auto &camera = computeCameraEndpoint(participant);
const auto &screen = computeScreenEndpoint(participant);
if (!camera.empty()) {
if (pinned.id == camera) {
if (pinned && large.id == camera) {
result->addAction(
tr::lng_group_call_context_unpin_camera(tr::now),
[=] { _call->pinVideoEndpoint(VideoEndpoint()); });
@ -1203,11 +1204,12 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
[=] { _call->pinVideoEndpoint(VideoEndpoint{
VideoEndpointType::Camera,
participantPeer,
camera }); });
camera });
});
}
}
if (!screen.empty()) {
if (pinned.id == screen) {
if (pinned && large.id == screen) {
result->addAction(
tr::lng_group_call_context_unpin_screen(tr::now),
[=] { _call->pinVideoEndpoint(VideoEndpoint()); });
@ -1217,7 +1219,8 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
[=] { _call->pinVideoEndpoint(VideoEndpoint{
VideoEndpointType::Screen,
participantPeer,
screen }); });
screen });
});
}
}
}
@ -1637,9 +1640,9 @@ void Members::setupList() {
}
void Members::trackViewportGeometry() {
_call->videoEndpointPinnedValue(
) | rpl::start_with_next([=](const VideoEndpoint &pinned) {
_viewport->showLarge(pinned);
_call->videoEndpointLargeValue(
) | rpl::start_with_next([=](const VideoEndpoint &large) {
_viewport->showLarge(large);
}, _viewport->lifetime());
const auto move = [=] {

View File

@ -1023,12 +1023,12 @@ void Panel::setupMembers() {
}
}, _callLifetime);
_call->videoEndpointPinnedValue(
) | rpl::start_with_next([=](const VideoEndpoint &pinned) {
if (pinned && mode() != PanelMode::Wide) {
_call->videoEndpointLargeValue(
) | rpl::start_with_next([=](const VideoEndpoint &large) {
if (large && mode() != PanelMode::Wide) {
enlargeVideo();
}
_viewport->showLarge(pinned);
_viewport->showLarge(large);
}, _callLifetime);
}
@ -1127,10 +1127,14 @@ void Panel::setupVideo(not_null<Viewport*> viewport) {
using namespace rpl::mappers;
const auto row = _members->lookupRow(track.peer);
Assert(row != nullptr);
auto pinned = rpl::combine(
_call->videoEndpointLargeValue(),
_call->videoEndpointPinnedValue()
) | rpl::map(_1 == endpoint && _2);
viewport->add(
endpoint,
VideoTileTrack{ track.track.get(), row },
_call->videoEndpointPinnedValue() | rpl::map(_1 == endpoint));
std::move(pinned));
};
for (const auto &[endpoint, track] : _call->activeVideoTracks()) {
setupTile(endpoint, track);
@ -1154,16 +1158,21 @@ void Panel::setupVideo(not_null<Viewport*> viewport) {
}, viewport->lifetime());
viewport->pinToggled(
) | rpl::start_with_next([=](const VideoPinToggle &value) {
_call->pinVideoEndpoint(
value.pinned ? value.endpoint : VideoEndpoint{});
) | rpl::start_with_next([=](bool pinned) {
_call->pinVideoEndpoint(pinned
? _call->videoEndpointLarge()
: VideoEndpoint{});
}, viewport->lifetime());
viewport->clicks(
) | rpl::filter([=] {
return (_mode.current() == PanelMode::Default);
}) | rpl::start_with_next([=](VideoEndpoint &&endpoint) {
_call->pinVideoEndpoint(std::move(endpoint));
) | rpl::start_with_next([=](VideoEndpoint &&endpoint) {
if (_call->videoEndpointLarge() == endpoint) {
_call->showVideoEndpointLarge({});
} else if (_call->videoEndpointPinned()) {
_call->pinVideoEndpoint(std::move(endpoint));
} else {
_call->showVideoEndpointLarge(std::move(endpoint));
}
}, viewport->lifetime());
viewport->qualityRequests(
@ -1787,8 +1796,8 @@ bool Panel::updateMode() {
if (_mode.current() == mode) {
return false;
}
if (!wide && _call->videoEndpointPinned()) {
_call->pinVideoEndpoint({});
if (!wide && _call->videoEndpointLarge()) {
_call->showVideoEndpointLarge({});
}
refreshVideoButtons(wide);
_niceTooltip.destroy();

View File

@ -157,10 +157,7 @@ void Viewport::handleMouseRelease(QPoint position, Qt::MouseButton button) {
} else if (!wide()) {
_clicks.fire_copy(tile->endpoint());
} else if (pressed.element == Selection::Element::PinButton) {
_pinToggles.fire({
.endpoint = tile->endpoint(),
.pinned = !tile->pinned(),
});
_pinToggles.fire(!tile->pinned());
}
}
}
@ -540,7 +537,7 @@ rpl::producer<int> Viewport::fullHeightValue() const {
return _fullHeight.value();
}
rpl::producer<VideoPinToggle> Viewport::pinToggled() const {
rpl::producer<bool> Viewport::pinToggled() const {
return _pinToggles.events();
}

View File

@ -21,7 +21,6 @@ struct ChosenRenderer;
namespace Calls {
class GroupCall;
struct VideoEndpoint;
struct VideoPinToggle;
struct VideoQualityRequest;
} // namespace Calls
@ -80,7 +79,7 @@ public:
[[nodiscard]] bool requireARGB32() const;
[[nodiscard]] int fullHeight() const;
[[nodiscard]] rpl::producer<int> fullHeightValue() const;
[[nodiscard]] rpl::producer<VideoPinToggle> pinToggled() const;
[[nodiscard]] rpl::producer<bool> pinToggled() const;
[[nodiscard]] rpl::producer<VideoEndpoint> clicks() const;
[[nodiscard]] rpl::producer<VideoQualityRequest> qualityRequests() const;
[[nodiscard]] rpl::producer<bool> mouseInsideValue() const;
@ -139,7 +138,7 @@ private:
int _scrollTop = 0;
QImage _shadow;
rpl::event_stream<VideoEndpoint> _clicks;
rpl::event_stream<VideoPinToggle> _pinToggles;
rpl::event_stream<bool> _pinToggles;
rpl::event_stream<VideoQualityRequest> _qualityRequests;
float64 _controlsShownRatio = 1.;
VideoTile *_large = nullptr;