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

View file

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

View file

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

View file

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

View file

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

View file

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