mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Switch between videos by left click.
This commit is contained in:
parent
7e8d1f7974
commit
3a321d64f6
5 changed files with 173 additions and 134 deletions
|
@ -47,6 +47,7 @@ constexpr auto kCheckLastSpokeInterval = crl::time(1000);
|
||||||
constexpr auto kCheckJoinedTimeout = 4 * crl::time(1000);
|
constexpr auto kCheckJoinedTimeout = 4 * crl::time(1000);
|
||||||
constexpr auto kUpdateSendActionEach = crl::time(500);
|
constexpr auto kUpdateSendActionEach = crl::time(500);
|
||||||
constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
|
constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
|
||||||
|
constexpr auto kFixLargeVideoDuration = 5 * crl::time(1000);
|
||||||
|
|
||||||
[[nodiscard]] std::unique_ptr<Webrtc::MediaDevices> CreateMediaDevices() {
|
[[nodiscard]] std::unique_ptr<Webrtc::MediaDevices> CreateMediaDevices() {
|
||||||
const auto &settings = Core::App().settings();
|
const auto &settings = Core::App().settings();
|
||||||
|
@ -61,15 +62,9 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
|
||||||
uint64 id,
|
uint64 id,
|
||||||
not_null<PeerData*> participantPeer) {
|
not_null<PeerData*> participantPeer) {
|
||||||
const auto call = peer->groupCall();
|
const auto call = peer->groupCall();
|
||||||
if (!id || !call || call->id() != id) {
|
return (id && call && call->id() == id)
|
||||||
return nullptr;
|
? call->participantByPeer(participantPeer)
|
||||||
}
|
: nullptr;
|
||||||
const auto &participants = call->participants();
|
|
||||||
const auto i = ranges::find(
|
|
||||||
participants,
|
|
||||||
participantPeer,
|
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
return (i != end(participants)) ? &*i : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] double TimestampFromMsgId(mtpMsgId msgId) {
|
[[nodiscard]] double TimestampFromMsgId(mtpMsgId msgId) {
|
||||||
|
@ -559,7 +554,7 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
|
||||||
newLarge = chooseLargeVideoEndpoint();
|
newLarge = chooseLargeVideoEndpoint();
|
||||||
}
|
}
|
||||||
if (_videoEndpointLarge.current() != newLarge) {
|
if (_videoEndpointLarge.current() != newLarge) {
|
||||||
_videoEndpointLarge = newLarge;
|
setVideoEndpointLarge(newLarge);
|
||||||
}
|
}
|
||||||
if (!updateCameraNotStreams.empty()) {
|
if (!updateCameraNotStreams.empty()) {
|
||||||
_streamsVideoUpdated.fire({ updateCameraNotStreams, false });
|
_streamsVideoUpdated.fire({ updateCameraNotStreams, false });
|
||||||
|
@ -624,7 +619,10 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
|
||||||
const auto wasSounding = data.was && data.was->sounding;
|
const auto wasSounding = data.was && data.was->sounding;
|
||||||
if (nowSpeaking == wasSpeaking && nowSounding == wasSounding) {
|
if (nowSpeaking == wasSpeaking && nowSounding == wasSounding) {
|
||||||
return;
|
return;
|
||||||
} else if (_videoEndpointPinned.current()) {
|
} else if (_videoEndpointPinned.current()
|
||||||
|
|| (_videoLargeShowTime
|
||||||
|
&& _videoLargeShowTime + kFixLargeVideoDuration
|
||||||
|
> crl::now())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (nowScreenEndpoint != newLarge.endpoint
|
if (nowScreenEndpoint != newLarge.endpoint
|
||||||
|
@ -880,7 +878,7 @@ void GroupCall::setMyEndpointType(
|
||||||
auto newLarge = _videoEndpointLarge.current();
|
auto newLarge = _videoEndpointLarge.current();
|
||||||
if (newLarge.endpoint == endpoint) {
|
if (newLarge.endpoint == endpoint) {
|
||||||
_videoEndpointPinned = false;
|
_videoEndpointPinned = false;
|
||||||
_videoEndpointLarge = chooseLargeVideoEndpoint();
|
setVideoEndpointLarge(chooseLargeVideoEndpoint());
|
||||||
}
|
}
|
||||||
_streamsVideoUpdated.fire({ endpoint, false });
|
_streamsVideoUpdated.fire({ endpoint, false });
|
||||||
}
|
}
|
||||||
|
@ -899,7 +897,7 @@ void GroupCall::setMyEndpointType(
|
||||||
&& nowLarge != EndpointType::Screen)
|
&& nowLarge != EndpointType::Screen)
|
||||||
|| (type == EndpointType::Camera
|
|| (type == EndpointType::Camera
|
||||||
&& nowLarge == EndpointType::None))) {
|
&& nowLarge == EndpointType::None))) {
|
||||||
_videoEndpointLarge = VideoEndpoint{ _joinAs, endpoint };
|
setVideoEndpointLarge(VideoEndpoint{ _joinAs, endpoint });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1132,34 +1130,30 @@ void GroupCall::leavePresentation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::applyMeInCallLocally() {
|
void GroupCall::applyMeInCallLocally() {
|
||||||
const auto call = _peer->groupCall();
|
const auto real = lookupReal();
|
||||||
if (!call || call->id() != _id) {
|
if (!real) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using Flag = MTPDgroupCallParticipant::Flag;
|
using Flag = MTPDgroupCallParticipant::Flag;
|
||||||
const auto &participants = call->participants();
|
const auto participant = real->participantByPeer(_joinAs);
|
||||||
const auto i = ranges::find(
|
const auto date = participant
|
||||||
participants,
|
? participant->date
|
||||||
_joinAs,
|
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
const auto date = (i != end(participants))
|
|
||||||
? i->date
|
|
||||||
: base::unixtime::now();
|
: base::unixtime::now();
|
||||||
const auto lastActive = (i != end(participants))
|
const auto lastActive = participant
|
||||||
? i->lastActive
|
? participant->lastActive
|
||||||
: TimeId(0);
|
: TimeId(0);
|
||||||
const auto volume = (i != end(participants))
|
const auto volume = participant
|
||||||
? i->volume
|
? participant->volume
|
||||||
: Group::kDefaultVolume;
|
: Group::kDefaultVolume;
|
||||||
const auto canSelfUnmute = (muted() != MuteState::ForceMuted)
|
const auto canSelfUnmute = (muted() != MuteState::ForceMuted)
|
||||||
&& (muted() != MuteState::RaisedHand);
|
&& (muted() != MuteState::RaisedHand);
|
||||||
const auto raisedHandRating = (muted() != MuteState::RaisedHand)
|
const auto raisedHandRating = (muted() != MuteState::RaisedHand)
|
||||||
? uint64(0)
|
? uint64(0)
|
||||||
: (i != end(participants))
|
: participant
|
||||||
? i->raisedHandRating
|
? participant->raisedHandRating
|
||||||
: FindLocalRaisedHandRating(participants);
|
: FindLocalRaisedHandRating(real->participants());
|
||||||
const auto params = (i != end(participants))
|
const auto params = participant
|
||||||
? i->videoParams.get()
|
? participant->videoParams.get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0))
|
const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0))
|
||||||
| (lastActive ? Flag::f_active_date : Flag(0))
|
| (lastActive ? Flag::f_active_date : Flag(0))
|
||||||
|
@ -1173,7 +1167,7 @@ void GroupCall::applyMeInCallLocally() {
|
||||||
? Flag::f_presentation
|
? Flag::f_presentation
|
||||||
: Flag(0))
|
: Flag(0))
|
||||||
| (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0));
|
| (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0));
|
||||||
call->applyLocalUpdate(
|
real->applyLocalUpdate(
|
||||||
MTP_updateGroupCallParticipants(
|
MTP_updateGroupCallParticipants(
|
||||||
inputCall(),
|
inputCall(),
|
||||||
MTP_vector<MTPGroupCallParticipant>(
|
MTP_vector<MTPGroupCallParticipant>(
|
||||||
|
@ -2013,17 +2007,15 @@ bool GroupCall::mediaChannelDescriptionsFill(
|
||||||
const auto addVideoChannel = [&](
|
const auto addVideoChannel = [&](
|
||||||
not_null<PeerData*> participantPeer,
|
not_null<PeerData*> participantPeer,
|
||||||
const auto field) {
|
const auto field) {
|
||||||
const auto i = ranges::find(
|
const auto participant = real->participantByPeer(
|
||||||
existing,
|
participantPeer);
|
||||||
participantPeer,
|
Assert(participant != nullptr);
|
||||||
&Data::GroupCallParticipant::peer);
|
Assert(participant->videoParams != nullptr);
|
||||||
Assert(i != end(existing));
|
const auto ¶ms = participant->videoParams.get()->*field;
|
||||||
Assert(i->videoParams != nullptr);
|
|
||||||
const auto ¶ms = i->videoParams.get()->*field;
|
|
||||||
Assert(!params.empty());
|
Assert(!params.empty());
|
||||||
add(Channel{
|
add(Channel{
|
||||||
.type = Channel::Type::Video,
|
.type = Channel::Type::Video,
|
||||||
.audioSsrc = i->ssrc,
|
.audioSsrc = participant->ssrc,
|
||||||
.videoInformation = params.json.toStdString(),
|
.videoInformation = params.json.toStdString(),
|
||||||
}, (field == &ParticipantVideoParams::screen));
|
}, (field == &ParticipantVideoParams::screen));
|
||||||
};
|
};
|
||||||
|
@ -2085,7 +2077,7 @@ void GroupCall::setIncomingVideoEndpoints(
|
||||||
newLarge = VideoEndpoint();
|
newLarge = VideoEndpoint();
|
||||||
}
|
}
|
||||||
if (newLarge.empty()) {
|
if (newLarge.empty()) {
|
||||||
_videoEndpointLarge = chooseLargeVideoEndpoint();
|
setVideoEndpointLarge(chooseLargeVideoEndpoint());
|
||||||
}
|
}
|
||||||
for (const auto &endpoint : removed) {
|
for (const auto &endpoint : removed) {
|
||||||
if (_activeVideoEndpoints.contains(endpoint)) {
|
if (_activeVideoEndpoints.contains(endpoint)) {
|
||||||
|
@ -2134,7 +2126,7 @@ void GroupCall::fillActiveVideoEndpoints() {
|
||||||
newLarge = VideoEndpoint();
|
newLarge = VideoEndpoint();
|
||||||
}
|
}
|
||||||
if (!newLarge) {
|
if (!newLarge) {
|
||||||
_videoEndpointLarge = chooseLargeVideoEndpoint();
|
setVideoEndpointLarge(chooseLargeVideoEndpoint());
|
||||||
}
|
}
|
||||||
for (const auto &[endpoint, type] : removed) {
|
for (const auto &[endpoint, type] : removed) {
|
||||||
if (_activeVideoEndpoints.remove(endpoint)) {
|
if (_activeVideoEndpoints.remove(endpoint)) {
|
||||||
|
@ -2494,16 +2486,30 @@ void GroupCall::sendSelfUpdate(SendUpdateType type) {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::pinVideoEndpoint(const VideoEndpoint &endpoint) {
|
void GroupCall::pinVideoEndpoint(VideoEndpoint endpoint) {
|
||||||
if (!endpoint) {
|
if (!endpoint) {
|
||||||
_videoEndpointPinned = false;
|
_videoEndpointPinned = false;
|
||||||
} else if (streamsVideo(endpoint.endpoint)) {
|
} else if (streamsVideo(endpoint.endpoint)) {
|
||||||
_videoEndpointPinned = false;
|
_videoEndpointPinned = false;
|
||||||
_videoEndpointLarge = endpoint;
|
setVideoEndpointLarge(std::move(endpoint));
|
||||||
_videoEndpointPinned = true;
|
_videoEndpointPinned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCall::showVideoEndpointLarge(VideoEndpoint endpoint) {
|
||||||
|
if (!streamsVideo(endpoint.endpoint)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_videoEndpointPinned = false;
|
||||||
|
setVideoEndpointLarge(std::move(endpoint));
|
||||||
|
_videoLargeShowTime = crl::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCall::setVideoEndpointLarge(VideoEndpoint endpoint) {
|
||||||
|
_videoEndpointLarge = endpoint;
|
||||||
|
_videoLargeShowTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::setCurrentAudioDevice(bool input, const QString &deviceId) {
|
void GroupCall::setCurrentAudioDevice(bool input, const QString &deviceId) {
|
||||||
if (input) {
|
if (input) {
|
||||||
_mediaDevices->switchToAudioInput(deviceId);
|
_mediaDevices->switchToAudioInput(deviceId);
|
||||||
|
@ -2572,13 +2578,9 @@ std::variant<int, not_null<UserData*>> GroupCall::inviteUsers(
|
||||||
}
|
}
|
||||||
const auto owner = &_peer->owner();
|
const auto owner = &_peer->owner();
|
||||||
const auto &invited = owner->invitedToCallUsers(_id);
|
const auto &invited = owner->invitedToCallUsers(_id);
|
||||||
const auto &participants = real->participants();
|
|
||||||
auto &&toInvite = users | ranges::views::filter([&](
|
auto &&toInvite = users | ranges::views::filter([&](
|
||||||
not_null<UserData*> user) {
|
not_null<UserData*> user) {
|
||||||
return !invited.contains(user) && !ranges::contains(
|
return !invited.contains(user) && !real->participantByPeer(user);
|
||||||
participants,
|
|
||||||
user,
|
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto count = 0;
|
auto count = 0;
|
||||||
|
|
|
@ -289,7 +289,7 @@ public:
|
||||||
[[nodiscard]] rpl::producer<bool> videoEndpointPinnedValue() const {
|
[[nodiscard]] rpl::producer<bool> videoEndpointPinnedValue() const {
|
||||||
return _videoEndpointPinned.value();
|
return _videoEndpointPinned.value();
|
||||||
}
|
}
|
||||||
void pinVideoEndpoint(const VideoEndpoint &endpoint);
|
void pinVideoEndpoint(VideoEndpoint endpoint);
|
||||||
[[nodiscard]] const VideoEndpoint &videoEndpointLarge() const {
|
[[nodiscard]] const VideoEndpoint &videoEndpointLarge() const {
|
||||||
return _videoEndpointLarge.current();
|
return _videoEndpointLarge.current();
|
||||||
}
|
}
|
||||||
|
@ -297,6 +297,7 @@ public:
|
||||||
-> rpl::producer<VideoEndpoint> {
|
-> rpl::producer<VideoEndpoint> {
|
||||||
return _videoEndpointLarge.value();
|
return _videoEndpointLarge.value();
|
||||||
}
|
}
|
||||||
|
void showVideoEndpointLarge(VideoEndpoint endpoint);
|
||||||
struct LargeTrack {
|
struct LargeTrack {
|
||||||
Webrtc::VideoTrack *track = nullptr;
|
Webrtc::VideoTrack *track = nullptr;
|
||||||
PeerData *peer = nullptr;
|
PeerData *peer = nullptr;
|
||||||
|
@ -451,6 +452,7 @@ private:
|
||||||
[[nodiscard]] VideoEndpoint chooseLargeVideoEndpoint() const;
|
[[nodiscard]] VideoEndpoint chooseLargeVideoEndpoint() const;
|
||||||
[[nodiscard]] EndpointType activeVideoEndpointType(
|
[[nodiscard]] EndpointType activeVideoEndpointType(
|
||||||
const std::string &endpoint) const;
|
const std::string &endpoint) const;
|
||||||
|
void setVideoEndpointLarge(VideoEndpoint endpoint);
|
||||||
|
|
||||||
void editParticipant(
|
void editParticipant(
|
||||||
not_null<PeerData*> participantPeer,
|
not_null<PeerData*> participantPeer,
|
||||||
|
@ -539,6 +541,7 @@ private:
|
||||||
rpl::variable<bool> _videoEndpointPinned;
|
rpl::variable<bool> _videoEndpointPinned;
|
||||||
std::unique_ptr<Webrtc::VideoTrack> _videoLargeTrackWrap;
|
std::unique_ptr<Webrtc::VideoTrack> _videoLargeTrackWrap;
|
||||||
rpl::variable<LargeTrack> _videoLargeTrack;
|
rpl::variable<LargeTrack> _videoLargeTrack;
|
||||||
|
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;
|
||||||
|
|
|
@ -159,6 +159,8 @@ private:
|
||||||
void setRowVideoEndpoint(
|
void setRowVideoEndpoint(
|
||||||
not_null<Row*> row,
|
not_null<Row*> row,
|
||||||
const std::string &endpoint);
|
const std::string &endpoint);
|
||||||
|
bool toggleRowVideo(not_null<PeerListRow*> row);
|
||||||
|
void showRowMenu(not_null<PeerListRow*> row);
|
||||||
|
|
||||||
void generateNarrowShadow();
|
void generateNarrowShadow();
|
||||||
void appendInvitedUsers();
|
void appendInvitedUsers();
|
||||||
|
@ -377,16 +379,13 @@ void Members::Controller::setupListChangeViewers() {
|
||||||
const auto row = i->second;
|
const auto row = i->second;
|
||||||
const auto real = _call->lookupReal();
|
const auto real = _call->lookupReal();
|
||||||
Assert(real != nullptr);
|
Assert(real != nullptr);
|
||||||
const auto &participants = real->participants();
|
const auto participant = real->participantByPeer(
|
||||||
const auto j = ranges::find(
|
row->peer());
|
||||||
participants,
|
if (!participant) {
|
||||||
row->peer(),
|
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
if (j == end(participants)) {
|
|
||||||
setRowVideoEndpoint(row, std::string());
|
setRowVideoEndpoint(row, std::string());
|
||||||
} else {
|
} else {
|
||||||
const auto &camera = computeCameraEndpoint(&*j);
|
const auto &camera = computeCameraEndpoint(participant);
|
||||||
const auto &screen = computeScreenEndpoint(&*j);
|
const auto &screen = computeScreenEndpoint(participant);
|
||||||
if (update.endpoint == camera
|
if (update.endpoint == camera
|
||||||
&& (_largeEndpoint != screen)
|
&& (_largeEndpoint != screen)
|
||||||
&& _call->streamsVideo(screen)) {
|
&& _call->streamsVideo(screen)) {
|
||||||
|
@ -730,12 +729,7 @@ const Data::GroupCallParticipant *Members::Controller::findParticipant(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (endpoint == _call->screenSharingEndpoint()
|
} else if (endpoint == _call->screenSharingEndpoint()
|
||||||
|| endpoint == _call->cameraSharingEndpoint()) {
|
|| endpoint == _call->cameraSharingEndpoint()) {
|
||||||
const auto &participants = real->participants();
|
return real->participantByPeer(_call->joinAs());
|
||||||
const auto i = ranges::find(
|
|
||||||
participants,
|
|
||||||
_call->joinAs(),
|
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
return (i != end(participants)) ? &*i : nullptr;
|
|
||||||
} else {
|
} else {
|
||||||
return real->participantByEndpoint(endpoint);
|
return real->participantByEndpoint(endpoint);
|
||||||
}
|
}
|
||||||
|
@ -784,7 +778,6 @@ bool Members::Controller::isMe(not_null<PeerData*> participantPeer) const {
|
||||||
void Members::Controller::prepareRows(not_null<Data::GroupCall*> real) {
|
void Members::Controller::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
auto foundMe = false;
|
auto foundMe = false;
|
||||||
auto changed = false;
|
auto changed = false;
|
||||||
const auto &participants = real->participants();
|
|
||||||
auto count = delegate()->peerListFullRowsCount();
|
auto count = delegate()->peerListFullRowsCount();
|
||||||
for (auto i = 0; i != count;) {
|
for (auto i = 0; i != count;) {
|
||||||
auto row = delegate()->peerListRowAt(i);
|
auto row = delegate()->peerListRowAt(i);
|
||||||
|
@ -794,11 +787,7 @@ void Members::Controller::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto contains = ranges::contains(
|
if (real->participantByPeer(participantPeer)) {
|
||||||
participants,
|
|
||||||
participantPeer,
|
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
if (contains) {
|
|
||||||
++i;
|
++i;
|
||||||
} else {
|
} else {
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -808,19 +797,16 @@ void Members::Controller::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
}
|
}
|
||||||
if (!foundMe) {
|
if (!foundMe) {
|
||||||
const auto me = _call->joinAs();
|
const auto me = _call->joinAs();
|
||||||
const auto i = ranges::find(
|
const auto participant = real->participantByPeer(me);
|
||||||
participants,
|
auto row = participant
|
||||||
me,
|
? createRow(*participant)
|
||||||
&Data::GroupCallParticipant::peer);
|
|
||||||
auto row = (i != end(participants))
|
|
||||||
? createRow(*i)
|
|
||||||
: createRowForMe();
|
: createRowForMe();
|
||||||
if (row) {
|
if (row) {
|
||||||
changed = true;
|
changed = true;
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto &participant : participants) {
|
for (const auto &participant : real->participants()) {
|
||||||
if (auto row = createRow(participant)) {
|
if (auto row = createRow(participant)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
|
@ -1089,6 +1075,12 @@ auto Members::Controller::kickParticipantRequests() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void Members::Controller::rowClicked(not_null<PeerListRow*> row) {
|
void Members::Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||||
|
if (!toggleRowVideo(row)) {
|
||||||
|
showRowMenu(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Members::Controller::showRowMenu(not_null<PeerListRow*> row) {
|
||||||
delegate()->peerListShowRowMenu(row, [=](not_null<Ui::PopupMenu*> menu) {
|
delegate()->peerListShowRowMenu(row, [=](not_null<Ui::PopupMenu*> menu) {
|
||||||
if (!_menu || _menu.get() != menu) {
|
if (!_menu || _menu.get() != menu) {
|
||||||
return;
|
return;
|
||||||
|
@ -1103,9 +1095,51 @@ void Members::Controller::rowClicked(not_null<PeerListRow*> row) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Members::Controller::toggleRowVideo(not_null<PeerListRow*> row) {
|
||||||
|
const auto real = _call->lookupReal();
|
||||||
|
if (!real) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto participantPeer = row->peer();
|
||||||
|
const auto isMe = (participantPeer == _call->joinAs());
|
||||||
|
const auto participant = real->participantByPeer(participantPeer);
|
||||||
|
if (!participant) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto params = participant->videoParams.get();
|
||||||
|
const auto empty = std::string();
|
||||||
|
const auto &camera = isMe
|
||||||
|
? _call->cameraSharingEndpoint()
|
||||||
|
: (params && _call->streamsVideo(params->camera.endpoint))
|
||||||
|
? params->camera.endpoint
|
||||||
|
: empty;
|
||||||
|
const auto &screen = isMe
|
||||||
|
? _call->screenSharingEndpoint()
|
||||||
|
: (params && _call->streamsVideo(params->screen.endpoint))
|
||||||
|
? params->screen.endpoint
|
||||||
|
: empty;
|
||||||
|
const auto &large = _call->videoEndpointLarge().endpoint;
|
||||||
|
const auto show = [&] {
|
||||||
|
if (!screen.empty() && large != screen) {
|
||||||
|
return screen;
|
||||||
|
} else if (!camera.empty() && large != camera) {
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
}();
|
||||||
|
if (show.empty()) {
|
||||||
|
return false;
|
||||||
|
} else if (_call->videoEndpointPinned()) {
|
||||||
|
_call->pinVideoEndpoint({ participantPeer, show });
|
||||||
|
} else {
|
||||||
|
_call->showVideoEndpointLarge({ participantPeer, show });
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Members::Controller::rowActionClicked(
|
void Members::Controller::rowActionClicked(
|
||||||
not_null<PeerListRow*> row) {
|
not_null<PeerListRow*> row) {
|
||||||
rowClicked(row);
|
showRowMenu(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> Members::Controller::rowContextMenu(
|
base::unique_qptr<Ui::PopupMenu> Members::Controller::rowContextMenu(
|
||||||
|
@ -1195,26 +1229,20 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
|
||||||
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()); });
|
||||||
} else {
|
} else if (const auto participant = real->participantByPeer(
|
||||||
const auto &participants = real->participants();
|
participantPeer)) {
|
||||||
const auto i = ranges::find(
|
const auto &camera = computeCameraEndpoint(participant);
|
||||||
participants,
|
const auto &screen = computeScreenEndpoint(participant);
|
||||||
participantPeer,
|
const auto streamsScreen = _call->streamsVideo(screen);
|
||||||
&Data::GroupCallParticipant::peer);
|
if (streamsScreen || _call->streamsVideo(camera)) {
|
||||||
if (i != end(participants)) {
|
const auto callback = [=] {
|
||||||
const auto &camera = computeCameraEndpoint(&*i);
|
_call->pinVideoEndpoint(VideoEndpoint{
|
||||||
const auto &screen = computeScreenEndpoint(&*i);
|
participantPeer,
|
||||||
const auto streamsScreen = _call->streamsVideo(screen);
|
streamsScreen ? screen : camera });
|
||||||
if (streamsScreen || _call->streamsVideo(camera)) {
|
};
|
||||||
const auto callback = [=] {
|
result->addAction(
|
||||||
_call->pinVideoEndpoint(VideoEndpoint{
|
tr::lng_group_call_context_pin_camera(tr::now),
|
||||||
participantPeer,
|
callback);
|
||||||
streamsScreen ? screen : camera });
|
|
||||||
};
|
|
||||||
result->addAction(
|
|
||||||
tr::lng_group_call_context_pin_camera(tr::now),
|
|
||||||
callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,17 @@ PeerData *GroupCall::participantPeerByScreenSsrc(uint32 ssrc) const {
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GroupCallParticipant *GroupCall::participantByPeer(
|
||||||
|
not_null<PeerData*> peer) const {
|
||||||
|
return const_cast<GroupCall*>(this)->findParticipant(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupCallParticipant *GroupCall::findParticipant(
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
|
const auto i = ranges::find(_participants, peer, &Participant::peer);
|
||||||
|
return (i != end(_participants)) ? &*i : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const GroupCallParticipant *GroupCall::participantByEndpoint(
|
const GroupCallParticipant *GroupCall::participantByEndpoint(
|
||||||
const std::string &endpoint) const {
|
const std::string &endpoint) const {
|
||||||
if (endpoint.empty()) {
|
if (endpoint.empty()) {
|
||||||
|
@ -683,24 +694,22 @@ void GroupCall::applyLastSpoke(
|
||||||
requestUnknownParticipants();
|
requestUnknownParticipants();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto j = ranges::find(
|
const auto participant = findParticipant(i->second);
|
||||||
_participants,
|
Assert(participant != nullptr);
|
||||||
i->second,
|
|
||||||
&Participant::peer);
|
|
||||||
Assert(j != end(_participants));
|
|
||||||
|
|
||||||
_speakingByActiveFinishes.remove(j->peer);
|
_speakingByActiveFinishes.remove(participant->peer);
|
||||||
const auto sounding = (when.anything + kSoundStatusKeptFor >= now)
|
const auto sounding = (when.anything + kSoundStatusKeptFor >= now)
|
||||||
&& j->canSelfUnmute;
|
&& participant->canSelfUnmute;
|
||||||
const auto speaking = sounding
|
const auto speaking = sounding
|
||||||
&& (when.voice + kSoundStatusKeptFor >= now);
|
&& (when.voice + kSoundStatusKeptFor >= now);
|
||||||
if (j->sounding != sounding || j->speaking != speaking) {
|
if (participant->sounding != sounding
|
||||||
const auto was = *j;
|
|| participant->speaking != speaking) {
|
||||||
j->sounding = sounding;
|
const auto was = *participant;
|
||||||
j->speaking = speaking;
|
participant->sounding = sounding;
|
||||||
|
participant->speaking = speaking;
|
||||||
_participantUpdates.fire({
|
_participantUpdates.fire({
|
||||||
.was = was,
|
.was = was,
|
||||||
.now = *j,
|
.now = *participant,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -722,41 +731,37 @@ void GroupCall::applyActiveUpdate(
|
||||||
if (inCall()) {
|
if (inCall()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto i = participantPeerLoaded
|
const auto participant = participantPeerLoaded
|
||||||
? ranges::find(
|
? findParticipant(participantPeerLoaded)
|
||||||
_participants,
|
: nullptr;
|
||||||
not_null{ participantPeerLoaded },
|
const auto loadByUserId = !participant || participant->onlyMinLoaded;
|
||||||
&Participant::peer)
|
|
||||||
: _participants.end();
|
|
||||||
const auto notFound = (i == end(_participants));
|
|
||||||
const auto loadByUserId = notFound || i->onlyMinLoaded;
|
|
||||||
if (loadByUserId) {
|
if (loadByUserId) {
|
||||||
_unknownSpokenPeerIds[participantPeerId] = when;
|
_unknownSpokenPeerIds[participantPeerId] = when;
|
||||||
requestUnknownParticipants();
|
requestUnknownParticipants();
|
||||||
}
|
}
|
||||||
if (notFound || !i->canSelfUnmute) {
|
if (!participant || !participant->canSelfUnmute) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto was = std::make_optional(*i);
|
const auto was = std::make_optional(*participant);
|
||||||
const auto now = crl::now();
|
const auto now = crl::now();
|
||||||
const auto elapsed = TimeId((now - when.anything) / crl::time(1000));
|
const auto elapsed = TimeId((now - when.anything) / crl::time(1000));
|
||||||
const auto lastActive = base::unixtime::now() - elapsed;
|
const auto lastActive = base::unixtime::now() - elapsed;
|
||||||
const auto finishes = when.anything + kSpeakingAfterActive;
|
const auto finishes = when.anything + kSpeakingAfterActive;
|
||||||
if (lastActive <= i->lastActive || finishes <= now) {
|
if (lastActive <= participant->lastActive || finishes <= now) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_speakingByActiveFinishes[i->peer] = finishes;
|
_speakingByActiveFinishes[participant->peer] = finishes;
|
||||||
if (!_speakingByActiveFinishTimer.isActive()) {
|
if (!_speakingByActiveFinishTimer.isActive()) {
|
||||||
_speakingByActiveFinishTimer.callOnce(finishes - now);
|
_speakingByActiveFinishTimer.callOnce(finishes - now);
|
||||||
}
|
}
|
||||||
|
|
||||||
i->lastActive = lastActive;
|
participant->lastActive = lastActive;
|
||||||
i->speaking = true;
|
participant->speaking = true;
|
||||||
i->canSelfUnmute = true;
|
participant->canSelfUnmute = true;
|
||||||
if (!was->speaking || !was->canSelfUnmute) {
|
if (!was->speaking || !was->canSelfUnmute) {
|
||||||
_participantUpdates.fire({
|
_participantUpdates.fire({
|
||||||
.was = was,
|
.was = was,
|
||||||
.now = *i,
|
.now = *participant,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -779,16 +784,14 @@ void GroupCall::checkFinishSpeakingByActive() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto participantPeer : stop) {
|
for (const auto participantPeer : stop) {
|
||||||
const auto i = ranges::find(
|
const auto participant = findParticipant(participantPeer);
|
||||||
_participants,
|
Assert(participant != nullptr);
|
||||||
participantPeer,
|
if (participant->speaking) {
|
||||||
&Participant::peer);
|
const auto was = *participant;
|
||||||
if (i->speaking) {
|
participant->speaking = false;
|
||||||
const auto was = *i;
|
|
||||||
i->speaking = false;
|
|
||||||
_participantUpdates.fire({
|
_participantUpdates.fire({
|
||||||
.was = was,
|
.was = was,
|
||||||
.now = *i,
|
.now = *participant,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,8 @@ public:
|
||||||
[[nodiscard]] PeerData *participantPeerByAudioSsrc(uint32 ssrc) const;
|
[[nodiscard]] PeerData *participantPeerByAudioSsrc(uint32 ssrc) const;
|
||||||
[[nodiscard]] PeerData *participantPeerByCameraSsrc(uint32 ssrc) const;
|
[[nodiscard]] PeerData *participantPeerByCameraSsrc(uint32 ssrc) const;
|
||||||
[[nodiscard]] PeerData *participantPeerByScreenSsrc(uint32 ssrc) const;
|
[[nodiscard]] PeerData *participantPeerByScreenSsrc(uint32 ssrc) const;
|
||||||
|
[[nodiscard]] const Participant *participantByPeer(
|
||||||
|
not_null<PeerData*> peer) const;
|
||||||
[[nodiscard]] const Participant *participantByEndpoint(
|
[[nodiscard]] const Participant *participantByEndpoint(
|
||||||
const std::string &endpoint) const;
|
const std::string &endpoint) const;
|
||||||
|
|
||||||
|
@ -178,6 +180,7 @@ private:
|
||||||
const MTPphone_GroupCall &call) const;
|
const MTPphone_GroupCall &call) const;
|
||||||
[[nodiscard]] bool processSavedFullCall();
|
[[nodiscard]] bool processSavedFullCall();
|
||||||
void finishParticipantsSliceRequest();
|
void finishParticipantsSliceRequest();
|
||||||
|
[[nodiscard]] Participant *findParticipant(not_null<PeerData*> peer);
|
||||||
|
|
||||||
void emplaceVideoSsrcs(const Participant &participant);
|
void emplaceVideoSsrcs(const Participant &participant);
|
||||||
void eraseVideoSsrcs(const Participant &participant);
|
void eraseVideoSsrcs(const Participant &participant);
|
||||||
|
|
Loading…
Add table
Reference in a new issue