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

View file

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

View file

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

View file

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