Special mute state for Push-to-Talk unmute.

This commit is contained in:
John Preston 2020-12-06 14:13:50 +04:00
parent 8f11868bb6
commit af4f10b1bb
4 changed files with 62 additions and 32 deletions

View File

@ -53,13 +53,14 @@ GroupCall::GroupCall(
, _api(&_channel->session().mtp())
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
, _checkJoinedTimer([=] { checkJoined(); }) {
_muted.changes(
) | rpl::start_with_next([=](MuteState state) {
_muted.value(
) | rpl::combine_previous(
) | rpl::start_with_next([=](MuteState previous, MuteState state) {
if (_instance) {
_instance->setIsMuted(state != MuteState::Active);
updateInstanceMuteState();
}
if (_mySsrc && state != MuteState::ForceMuted) {
sendMutedUpdate();
if (_mySsrc) {
maybeSendMutedUpdate(previous);
}
}, _lifetime);
@ -200,9 +201,9 @@ void GroupCall::rejoin() {
const auto json = QJsonDocument(root).toJson(
QJsonDocument::Compact);
const auto muted = _muted.current();
const auto wasMuteState = muted();
_api.request(MTPphone_JoinGroupCall(
MTP_flags((muted != MuteState::Active)
MTP_flags((wasMuteState != MuteState::Active)
? MTPphone_JoinGroupCall::Flag::f_muted
: MTPphone_JoinGroupCall::Flag(0)),
inputCall(),
@ -213,11 +214,7 @@ void GroupCall::rejoin() {
? State::Joined
: State::Connecting);
applySelfInCallLocally();
if (_muted.current() != muted) {
sendMutedUpdate();
}
maybeSendMutedUpdate(wasMuteState);
_channel->session().api().applyUpdates(updates);
}).fail([=](const RPCError &error) {
LOG(("Call Error: Could not join, error: %1"
@ -251,12 +248,11 @@ void GroupCall::applySelfInCallLocally() {
const auto lastActive = (i != end(participants))
? i->lastActive
: TimeId(0);
const auto muted = (_muted.current() != MuteState::Active);
const auto cantSelfUnmute = (_muted.current() == MuteState::ForceMuted);
const auto flags = (cantSelfUnmute ? Flag(0) : Flag::f_can_self_unmute)
const auto canSelfUnmute = (muted() != MuteState::ForceMuted);
const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0))
| (lastActive ? Flag::f_active_date : Flag(0))
| (_mySsrc ? Flag(0) : Flag::f_left)
| (muted ? Flag::f_muted : Flag(0));
| ((muted() != MuteState::Active) ? Flag::f_muted : Flag(0));
call->applyUpdateChecked(
MTP_updateGroupCallParticipants(
inputCall(),
@ -488,11 +484,19 @@ void GroupCall::createAndStartController() {
LOG(("Call Info: Creating group instance"));
_instance = std::make_unique<tgcalls::GroupInstanceImpl>(
std::move(descriptor));
_instance->setIsMuted(_muted.current() != MuteState::Active);
updateInstanceMuteState();
//raw->setAudioOutputDuckingEnabled(settings.callAudioDuckingEnabled());
}
void GroupCall::updateInstanceMuteState() {
Expects(_instance != nullptr);
const auto state = muted();
_instance->setIsMuted(state != MuteState::Active
&& state != MuteState::PushToTalk);
}
void GroupCall::handleLevelsUpdated(
gsl::span<const std::pair<std::uint32_t, float>> data) {
Expects(!data.empty());
@ -609,10 +613,23 @@ void GroupCall::setInstanceConnected(bool connected) {
}
}
void GroupCall::maybeSendMutedUpdate(MuteState previous) {
// Send only Active <-> !Active changes.
const auto now = muted();
const auto wasActive = (previous == MuteState::Active);
const auto nowActive = (now == MuteState::Active);
if (now == MuteState::ForceMuted
|| previous == MuteState::ForceMuted
|| (nowActive == wasActive)) {
return;
}
sendMutedUpdate();
}
void GroupCall::sendMutedUpdate() {
_api.request(_updateMuteRequestId).cancel();
_updateMuteRequestId = _api.request(MTPphone_EditGroupCallMember(
MTP_flags((_muted.current() != MuteState::Active)
MTP_flags((muted() != MuteState::Active)
? MTPphone_EditGroupCallMember::Flag::f_muted
: MTPphone_EditGroupCallMember::Flag(0)),
inputCall(),
@ -758,8 +775,9 @@ void GroupCall::applyGlobalShortcutChanges() {
}
_pushToTalk = shortcut;
_shortcutManager->startWatching(_pushToTalk, [=](bool pressed) {
if (_muted.current() != MuteState::ForceMuted) {
setMuted(pressed ? MuteState::Active : MuteState::Muted);
if (muted() != MuteState::ForceMuted
&& muted() != MuteState::Active) {
setMuted(pressed ? MuteState::PushToTalk : MuteState::Muted);
}
});
}

View File

@ -28,10 +28,17 @@ namespace Calls {
enum class MuteState {
Active,
PushToTalk,
Muted,
ForceMuted,
};
[[nodiscard]] inline auto MapPushToTalkToActive() {
return rpl::map([=](MuteState state) {
return (state == MuteState::PushToTalk) ? MuteState::Active : state;
});
}
struct LevelUpdate {
uint32 ssrc = 0;
float value = 0.;
@ -132,7 +139,9 @@ private:
void setState(State state);
void finish(FinishType type);
void maybeSendMutedUpdate(MuteState previous);
void sendMutedUpdate();
void updateInstanceMuteState();
void applySelfInCallLocally();
void rejoin();

View File

@ -317,13 +317,13 @@ void GroupPanel::hangup(bool discardCallChecked) {
void GroupPanel::initControls() {
_mute->clicks(
) | rpl::filter([=](Qt::MouseButton button) {
return (button == Qt::LeftButton);
return (button == Qt::LeftButton)
&& _call
&& (_call->muted() != MuteState::ForceMuted);
}) | rpl::start_with_next([=] {
if (_call && _call->muted() != MuteState::ForceMuted) {
_call->setMuted((_call->muted() == MuteState::Active)
? MuteState::Muted
: MuteState::Active);
}
_call->setMuted((_call->muted() == MuteState::Muted)
? MuteState::Active
: MuteState::Muted);
}, _mute->lifetime());
_hangup->setClickedCallback([=] { hangup(false); });
@ -381,19 +381,20 @@ void GroupPanel::initWithCall(GroupCall *call) {
using namespace rpl::mappers;
rpl::combine(
_call->mutedValue(),
_call->mutedValue() | MapPushToTalkToActive(),
_call->stateValue() | rpl::map(
_1 == State::Creating
|| _1 == State::Joining
|| _1 == State::Connecting
)
) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](MuteState mute, bool connecting) {
_mute->setState(Ui::CallMuteButtonState{
.text = (connecting
? tr::lng_group_call_connecting(tr::now)
: mute == MuteState::ForceMuted
? tr::lng_group_call_force_muted(tr::now)
: mute != MuteState::Active
: mute == MuteState::Muted
? tr::lng_group_call_unmute(tr::now)
: tr::lng_group_call_you_are_live(tr::now)),
.type = (connecting

View File

@ -198,9 +198,9 @@ void TopBar::initControls() {
call->setMuted(!call->muted());
} else if (const auto group = _groupCall.get()) {
if (group->muted() != MuteState::ForceMuted) {
group->setMuted((group->muted() == MuteState::Active)
? MuteState::Muted
: MuteState::Active);
group->setMuted((group->muted() == MuteState::Muted)
? MuteState::Active
: MuteState::Muted);
}
}
});
@ -212,7 +212,9 @@ void TopBar::initControls() {
_call ? mapToState(_call->muted()) : _groupCall->muted());
auto muted = _call
? _call->mutedValue() | rpl::map(mapToState)
: _groupCall->mutedValue();
: (_groupCall->mutedValue()
| MapPushToTalkToActive()
| rpl::distinct_until_changed());
std::move(
muted
) | rpl::start_with_next([=](MuteState state) {