mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Auto-switch large video by speaking participant.
This commit is contained in:
parent
8bde53cd0f
commit
6a001f2e6c
4 changed files with 60 additions and 6 deletions
|
@ -48,7 +48,8 @@ constexpr auto kCheckLastSpokeInterval = crl::time(1000);
|
|||
constexpr auto kCheckJoinedTimeout = 4 * crl::time(1000);
|
||||
constexpr auto kUpdateSendActionEach = crl::time(500);
|
||||
constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
|
||||
constexpr auto kFixLargeVideoDuration = 5 * crl::time(1000);
|
||||
constexpr auto kFixManualLargeVideoDuration = 5 * crl::time(1000);
|
||||
constexpr auto kFixSpeakingLargeVideoDuration = 3 * crl::time(1000);
|
||||
|
||||
[[nodiscard]] std::unique_ptr<Webrtc::MediaDevices> CreateMediaDevices() {
|
||||
const auto &settings = Core::App().settings();
|
||||
|
@ -629,6 +630,40 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
|
|||
return ssrcs->contains(ssrc);
|
||||
});
|
||||
}, _lifetime);
|
||||
|
||||
real->participantSpeaking(
|
||||
) | rpl::filter([=] {
|
||||
return _videoEndpointLarge.current();
|
||||
}) | rpl::start_with_next([=](not_null<Data::GroupCallParticipant*> p) {
|
||||
const auto now = crl::now();
|
||||
if (_videoEndpointLarge.current().peer == p->peer) {
|
||||
_videoLargeTillTime = std::max(
|
||||
_videoLargeTillTime,
|
||||
now + kFixSpeakingLargeVideoDuration);
|
||||
return;
|
||||
} else if (videoEndpointPinned() || _videoLargeTillTime > now) {
|
||||
return;
|
||||
}
|
||||
using Type = VideoEndpointType;
|
||||
if (p->cameraEndpoint().empty() && p->screenEndpoint().empty()) {
|
||||
return;
|
||||
}
|
||||
const auto tryEndpoint = [&](Type type, const std::string &id) {
|
||||
if (id.empty()) {
|
||||
return false;
|
||||
}
|
||||
const auto endpoint = VideoEndpoint{ type, p->peer, id };
|
||||
if (!shownVideoTracks().contains(endpoint)) {
|
||||
return false;
|
||||
}
|
||||
setVideoEndpointLarge(endpoint);
|
||||
return true;
|
||||
};
|
||||
if (tryEndpoint(Type::Screen, p->screenEndpoint())
|
||||
|| tryEndpoint(Type::Camera, p->cameraEndpoint())) {
|
||||
_videoLargeTillTime = now + kFixSpeakingLargeVideoDuration;
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void GroupCall::checkGlobalShortcutAvailability() {
|
||||
|
@ -2335,12 +2370,16 @@ void GroupCall::checkLastSpoke() {
|
|||
return;
|
||||
}
|
||||
|
||||
constexpr auto kKeepInListFor = kCheckLastSpokeInterval * 2;
|
||||
static_assert(Data::GroupCall::kSoundStatusKeptFor
|
||||
<= kKeepInListFor - (kCheckLastSpokeInterval / 3));
|
||||
|
||||
auto hasRecent = false;
|
||||
const auto now = crl::now();
|
||||
auto list = base::take(_lastSpoke);
|
||||
for (auto i = list.begin(); i != list.end();) {
|
||||
const auto [ssrc, when] = *i;
|
||||
if (when.anything + kCheckLastSpokeInterval >= now) {
|
||||
if (when.anything + kKeepInListFor >= now) {
|
||||
hasRecent = true;
|
||||
++i;
|
||||
} else {
|
||||
|
@ -2551,9 +2590,12 @@ void GroupCall::pinVideoEndpoint(VideoEndpoint endpoint) {
|
|||
}
|
||||
|
||||
void GroupCall::showVideoEndpointLarge(VideoEndpoint endpoint) {
|
||||
if (_videoEndpointLarge.current() == endpoint) {
|
||||
return;
|
||||
}
|
||||
_videoEndpointPinned = false;
|
||||
setVideoEndpointLarge(std::move(endpoint));
|
||||
_videoLargeShowTime = crl::now();
|
||||
_videoLargeTillTime = crl::now() + kFixManualLargeVideoDuration;
|
||||
}
|
||||
|
||||
void GroupCall::setVideoEndpointLarge(VideoEndpoint endpoint) {
|
||||
|
|
|
@ -592,7 +592,7 @@ private:
|
|||
base::flat_set<VideoEndpoint> _shownVideoTracks;
|
||||
rpl::variable<VideoEndpoint> _videoEndpointLarge;
|
||||
rpl::variable<bool> _videoEndpointPinned = false;
|
||||
crl::time _videoLargeShowTime = 0;
|
||||
crl::time _videoLargeTillTime = 0;
|
||||
base::flat_map<uint32, Data::LastSpokeTimes> _lastSpoke;
|
||||
rpl::event_stream<Group::RejoinEvent> _rejoinEvents;
|
||||
rpl::event_stream<> _allowedToSpeakNotifications;
|
||||
|
|
|
@ -251,6 +251,11 @@ auto GroupCall::participantUpdated() const
|
|||
return _participantUpdates.events();
|
||||
}
|
||||
|
||||
auto GroupCall::participantSpeaking() const
|
||||
-> rpl::producer<not_null<Participant*>> {
|
||||
return _participantSpeaking.events();
|
||||
}
|
||||
|
||||
void GroupCall::enqueueUpdate(const MTPUpdate &update) {
|
||||
update.match([&](const MTPDupdateGroupCall &updateData) {
|
||||
updateData.vcall().match([&](const MTPDgroupCall &data) {
|
||||
|
@ -658,6 +663,9 @@ void GroupCall::applyLastSpoke(
|
|||
&& participant->canSelfUnmute;
|
||||
const auto speaking = sounding
|
||||
&& (when.voice + kSoundStatusKeptFor >= now);
|
||||
if (speaking) {
|
||||
_participantSpeaking.fire({ participant });
|
||||
}
|
||||
if (participant->sounding != sounding
|
||||
|| participant->speaking != speaking) {
|
||||
const auto was = *participant;
|
||||
|
|
|
@ -105,7 +105,7 @@ public:
|
|||
std::optional<Participant> now;
|
||||
};
|
||||
|
||||
static constexpr auto kSoundStatusKeptFor = crl::time(1350);
|
||||
static constexpr auto kSoundStatusKeptFor = crl::time(1500);
|
||||
|
||||
[[nodiscard]] auto participants() const
|
||||
-> const std::vector<Participant> &;
|
||||
|
@ -118,7 +118,10 @@ public:
|
|||
const std::string &endpoint) const;
|
||||
|
||||
[[nodiscard]] rpl::producer<> participantsReloaded();
|
||||
[[nodiscard]] rpl::producer<ParticipantUpdate> participantUpdated() const;
|
||||
[[nodiscard]] auto participantUpdated() const
|
||||
-> rpl::producer<ParticipantUpdate>;
|
||||
[[nodiscard]] auto participantSpeaking() const
|
||||
-> rpl::producer<not_null<Participant*>>;
|
||||
|
||||
void enqueueUpdate(const MTPUpdate &update);
|
||||
void applyLocalUpdate(
|
||||
|
@ -222,6 +225,7 @@ private:
|
|||
mtpRequestId _unknownParticipantPeersRequestId = 0;
|
||||
|
||||
rpl::event_stream<ParticipantUpdate> _participantUpdates;
|
||||
rpl::event_stream<not_null<Participant*>> _participantSpeaking;
|
||||
rpl::event_stream<> _participantsReloaded;
|
||||
|
||||
bool _joinMuted = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue