mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +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 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);
|
constexpr auto kFixManualLargeVideoDuration = 5 * crl::time(1000);
|
||||||
|
constexpr auto kFixSpeakingLargeVideoDuration = 3 * 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();
|
||||||
|
@ -629,6 +630,40 @@ void GroupCall::subscribeToReal(not_null<Data::GroupCall*> real) {
|
||||||
return ssrcs->contains(ssrc);
|
return ssrcs->contains(ssrc);
|
||||||
});
|
});
|
||||||
}, _lifetime);
|
}, _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() {
|
void GroupCall::checkGlobalShortcutAvailability() {
|
||||||
|
@ -2335,12 +2370,16 @@ void GroupCall::checkLastSpoke() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr auto kKeepInListFor = kCheckLastSpokeInterval * 2;
|
||||||
|
static_assert(Data::GroupCall::kSoundStatusKeptFor
|
||||||
|
<= kKeepInListFor - (kCheckLastSpokeInterval / 3));
|
||||||
|
|
||||||
auto hasRecent = false;
|
auto hasRecent = false;
|
||||||
const auto now = crl::now();
|
const auto now = crl::now();
|
||||||
auto list = base::take(_lastSpoke);
|
auto list = base::take(_lastSpoke);
|
||||||
for (auto i = list.begin(); i != list.end();) {
|
for (auto i = list.begin(); i != list.end();) {
|
||||||
const auto [ssrc, when] = *i;
|
const auto [ssrc, when] = *i;
|
||||||
if (when.anything + kCheckLastSpokeInterval >= now) {
|
if (when.anything + kKeepInListFor >= now) {
|
||||||
hasRecent = true;
|
hasRecent = true;
|
||||||
++i;
|
++i;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2551,9 +2590,12 @@ void GroupCall::pinVideoEndpoint(VideoEndpoint endpoint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::showVideoEndpointLarge(VideoEndpoint endpoint) {
|
void GroupCall::showVideoEndpointLarge(VideoEndpoint endpoint) {
|
||||||
|
if (_videoEndpointLarge.current() == endpoint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_videoEndpointPinned = false;
|
_videoEndpointPinned = false;
|
||||||
setVideoEndpointLarge(std::move(endpoint));
|
setVideoEndpointLarge(std::move(endpoint));
|
||||||
_videoLargeShowTime = crl::now();
|
_videoLargeTillTime = crl::now() + kFixManualLargeVideoDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::setVideoEndpointLarge(VideoEndpoint endpoint) {
|
void GroupCall::setVideoEndpointLarge(VideoEndpoint endpoint) {
|
||||||
|
|
|
@ -592,7 +592,7 @@ private:
|
||||||
base::flat_set<VideoEndpoint> _shownVideoTracks;
|
base::flat_set<VideoEndpoint> _shownVideoTracks;
|
||||||
rpl::variable<VideoEndpoint> _videoEndpointLarge;
|
rpl::variable<VideoEndpoint> _videoEndpointLarge;
|
||||||
rpl::variable<bool> _videoEndpointPinned = false;
|
rpl::variable<bool> _videoEndpointPinned = false;
|
||||||
crl::time _videoLargeShowTime = 0;
|
crl::time _videoLargeTillTime = 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;
|
||||||
|
|
|
@ -251,6 +251,11 @@ auto GroupCall::participantUpdated() const
|
||||||
return _participantUpdates.events();
|
return _participantUpdates.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto GroupCall::participantSpeaking() const
|
||||||
|
-> rpl::producer<not_null<Participant*>> {
|
||||||
|
return _participantSpeaking.events();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::enqueueUpdate(const MTPUpdate &update) {
|
void GroupCall::enqueueUpdate(const MTPUpdate &update) {
|
||||||
update.match([&](const MTPDupdateGroupCall &updateData) {
|
update.match([&](const MTPDupdateGroupCall &updateData) {
|
||||||
updateData.vcall().match([&](const MTPDgroupCall &data) {
|
updateData.vcall().match([&](const MTPDgroupCall &data) {
|
||||||
|
@ -658,6 +663,9 @@ void GroupCall::applyLastSpoke(
|
||||||
&& participant->canSelfUnmute;
|
&& participant->canSelfUnmute;
|
||||||
const auto speaking = sounding
|
const auto speaking = sounding
|
||||||
&& (when.voice + kSoundStatusKeptFor >= now);
|
&& (when.voice + kSoundStatusKeptFor >= now);
|
||||||
|
if (speaking) {
|
||||||
|
_participantSpeaking.fire({ participant });
|
||||||
|
}
|
||||||
if (participant->sounding != sounding
|
if (participant->sounding != sounding
|
||||||
|| participant->speaking != speaking) {
|
|| participant->speaking != speaking) {
|
||||||
const auto was = *participant;
|
const auto was = *participant;
|
||||||
|
|
|
@ -105,7 +105,7 @@ public:
|
||||||
std::optional<Participant> now;
|
std::optional<Participant> now;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr auto kSoundStatusKeptFor = crl::time(1350);
|
static constexpr auto kSoundStatusKeptFor = crl::time(1500);
|
||||||
|
|
||||||
[[nodiscard]] auto participants() const
|
[[nodiscard]] auto participants() const
|
||||||
-> const std::vector<Participant> &;
|
-> const std::vector<Participant> &;
|
||||||
|
@ -118,7 +118,10 @@ public:
|
||||||
const std::string &endpoint) const;
|
const std::string &endpoint) const;
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> participantsReloaded();
|
[[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 enqueueUpdate(const MTPUpdate &update);
|
||||||
void applyLocalUpdate(
|
void applyLocalUpdate(
|
||||||
|
@ -222,6 +225,7 @@ private:
|
||||||
mtpRequestId _unknownParticipantPeersRequestId = 0;
|
mtpRequestId _unknownParticipantPeersRequestId = 0;
|
||||||
|
|
||||||
rpl::event_stream<ParticipantUpdate> _participantUpdates;
|
rpl::event_stream<ParticipantUpdate> _participantUpdates;
|
||||||
|
rpl::event_stream<not_null<Participant*>> _participantSpeaking;
|
||||||
rpl::event_stream<> _participantsReloaded;
|
rpl::event_stream<> _participantsReloaded;
|
||||||
|
|
||||||
bool _joinMuted = false;
|
bool _joinMuted = false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue