Separate Call/GroupCall delegates and Instance.

This commit is contained in:
John Preston 2021-04-22 20:05:17 +04:00
parent 6e34360f7e
commit c93ddf6aac
23 changed files with 422 additions and 262 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1107,7 +1107,9 @@ void PeerListContent::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
const auto clip = e->rect(); const auto clip = e->rect();
p.fillRect(clip, _st.item.button.textBg); if (_mode != Mode::Custom) {
p.fillRect(clip, _st.item.button.textBg);
}
const auto repaintByStatusAfter = _repaintByStatus.remainingTime(); const auto repaintByStatusAfter = _repaintByStatus.remainingTime();
auto repaintAfterMin = repaintByStatusAfter; auto repaintAfterMin = repaintByStatusAfter;

View file

@ -736,7 +736,7 @@ groupCallMemberRaisedHand: icon {{ "calls/group_calls_raised_hand", groupCallMem
groupCallSettingsInner: IconButton(callButton) { groupCallSettingsInner: IconButton(callButton) {
iconPosition: point(-1px, 22px); iconPosition: point(-1px, 22px);
icon: icon {{ "calls/call_settings", groupCallIconFg }}; icon: icon {{ "calls/calls_settings", groupCallIconFg }};
ripple: RippleAnimation(defaultRippleAnimation) { ripple: RippleAnimation(defaultRippleAnimation) {
color: callMuteRipple; color: callMuteRipple;
} }
@ -1022,3 +1022,5 @@ desktopCaptureSourceSkip: 12px;
groupCallNarrowSkip: 9px; groupCallNarrowSkip: 9px;
groupCallNarrowRowSkip: 8px; groupCallNarrowRowSkip: 8px;
groupCallNarrowSize: size(90px, 90px); groupCallNarrowSize: size(90px, 90px);
groupCallWideModeWidthMin: 800px;
groupCallWideModeSize: size(960px, 520px);

View file

@ -161,8 +161,12 @@ Call::Call(
, _user(user) , _user(user)
, _api(&_user->session().mtp()) , _api(&_user->session().mtp())
, _type(type) , _type(type)
, _videoIncoming(std::make_unique<Webrtc::VideoTrack>(StartVideoState(video))) , _videoIncoming(
, _videoOutgoing(std::make_unique<Webrtc::VideoTrack>(StartVideoState(video))) { std::make_unique<Webrtc::VideoTrack>(
StartVideoState(video)))
, _videoOutgoing(
std::make_unique<Webrtc::VideoTrack>(
StartVideoState(video))) {
_discardByTimeoutTimer.setCallback([=] { hangup(); }); _discardByTimeoutTimer.setCallback([=] { hangup(); });
if (_type == Type::Outgoing) { if (_type == Type::Outgoing) {

View file

@ -53,6 +53,11 @@ struct Error {
QString details; QString details;
}; };
enum class CallType {
Incoming,
Outgoing,
};
class Call : public base::has_weak_ptr { class Call : public base::has_weak_ptr {
public: public:
class Delegate { class Delegate {
@ -81,11 +86,12 @@ public:
static constexpr auto kSoundSampleMs = 100; static constexpr auto kSoundSampleMs = 100;
enum class Type { using Type = CallType;
Incoming, Call(
Outgoing, not_null<Delegate*> delegate,
}; not_null<UserData*> user,
Call(not_null<Delegate*> delegate, not_null<UserData*> user, Type type, bool video); Type type,
bool video);
[[nodiscard]] Type type() const { [[nodiscard]] Type type() const {
return _type; return _type;

View file

@ -7,7 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "calls/calls_call.h"
#include "calls/group/calls_group_common.h" #include "calls/group/calls_group_common.h"
#include "calls/group/calls_choose_join_as.h"
#include "calls/group/calls_group_call.h"
#include "mtproto/mtproto_dh_utils.h" #include "mtproto/mtproto_dh_utils.h"
#include "core/application.h" #include "core/application.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -41,9 +44,128 @@ namespace {
constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * crl::time(1000); constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * crl::time(1000);
using CallSound = Call::Delegate::CallSound;
using GroupCallSound = GroupCall::Delegate::GroupCallSound;
} // namespace } // namespace
Instance::Instance() = default; class Instance::Delegate final
: public Call::Delegate
, public GroupCall::Delegate {
public:
explicit Delegate(not_null<Instance*> instance);
DhConfig getDhConfig() const override;
void callFinished(not_null<Call*> call) override;
void callFailed(not_null<Call*> call) override;
void callRedial(not_null<Call*> call) override;
void callRequestPermissionsOrFail(
Fn<void()> onSuccess,
bool video) override;
void callPlaySound(CallSound sound) override;
auto callGetVideoCapture()
-> std::shared_ptr<tgcalls::VideoCaptureInterface> override;
void groupCallFinished(not_null<GroupCall*> call) override;
void groupCallFailed(not_null<GroupCall*> call) override;
void groupCallRequestPermissionsOrFail(Fn<void()> onSuccess) override;
void groupCallPlaySound(GroupCallSound sound) override;
auto groupCallGetVideoCapture(const QString &deviceId)
-> std::shared_ptr<tgcalls::VideoCaptureInterface> override;
private:
const not_null<Instance*> _instance;
};
Instance::Delegate::Delegate(not_null<Instance*> instance)
: _instance(instance) {
}
DhConfig Instance::Delegate::getDhConfig() const {
return *_instance->_cachedDhConfig;
}
void Instance::Delegate::callFinished(not_null<Call*> call) {
crl::on_main(call, [=] {
_instance->destroyCall(call);
});
}
void Instance::Delegate::callFailed(not_null<Call*> call) {
crl::on_main(call, [=] {
_instance->destroyCall(call);
});
}
void Instance::Delegate::callRedial(not_null<Call*> call) {
if (_instance->_currentCall.get() == call) {
_instance->refreshDhConfig();
}
}
void Instance::Delegate::callRequestPermissionsOrFail(
Fn<void()> onSuccess,
bool video) {
_instance->requestPermissionsOrFail(std::move(onSuccess), video);
}
void Instance::Delegate::callPlaySound(CallSound sound) {
_instance->playSoundOnce([&] {
switch (sound) {
case CallSound::Busy: return "call_busy";
case CallSound::Ended: return "call_end";
case CallSound::Connecting: return "call_connect";
}
Unexpected("CallSound in Instance::callPlaySound.");
}());
}
auto Instance::Delegate::callGetVideoCapture()
-> std::shared_ptr<tgcalls::VideoCaptureInterface> {
return _instance->getVideoCapture();
}
void Instance::Delegate::groupCallFinished(not_null<GroupCall*> call) {
crl::on_main(call, [=] {
_instance->destroyGroupCall(call);
});
}
void Instance::Delegate::groupCallFailed(not_null<GroupCall*> call) {
crl::on_main(call, [=] {
_instance->destroyGroupCall(call);
});
}
void Instance::Delegate::groupCallRequestPermissionsOrFail(
Fn<void()> onSuccess) {
_instance->requestPermissionsOrFail(std::move(onSuccess), false);
}
void Instance::Delegate::groupCallPlaySound(GroupCallSound sound) {
_instance->playSoundOnce([&] {
switch (sound) {
case GroupCallSound::Started: return "group_call_start";
case GroupCallSound::Ended: return "group_call_end";
case GroupCallSound::AllowedToSpeak: return "group_call_allowed";
case GroupCallSound::Connecting: return "group_call_connect";
}
Unexpected("GroupCallSound in Instance::groupCallPlaySound.");
}());
}
auto Instance::Delegate::groupCallGetVideoCapture(const QString &deviceId)
-> std::shared_ptr<tgcalls::VideoCaptureInterface> {
return _instance->getVideoCapture(deviceId);
}
Instance::Instance()
: _delegate(std::make_unique<Delegate>(this))
, _cachedDhConfig(std::make_unique<DhConfig>())
, _chooseJoinAs(std::make_unique<Group::ChooseJoinAsProcess>()) {
}
Instance::~Instance() = default; Instance::~Instance() = default;
@ -72,7 +194,7 @@ void Instance::startOrJoinGroupCall(
: peer->groupCall() : peer->groupCall()
? Group::ChooseJoinAsProcess::Context::Join ? Group::ChooseJoinAsProcess::Context::Join
: Group::ChooseJoinAsProcess::Context::Create; : Group::ChooseJoinAsProcess::Context::Create;
_chooseJoinAs.start(peer, context, [=](object_ptr<Ui::BoxContent> box) { _chooseJoinAs->start(peer, context, [=](object_ptr<Ui::BoxContent> box) {
Ui::show(std::move(box), Ui::LayerOption::KeepOther); Ui::show(std::move(box), Ui::LayerOption::KeepOther);
}, [=](QString text) { }, [=](QString text) {
Ui::Toast::Show(text); Ui::Toast::Show(text);
@ -85,36 +207,6 @@ void Instance::startOrJoinGroupCall(
}); });
} }
void Instance::callFinished(not_null<Call*> call) {
crl::on_main(call, [=] {
destroyCall(call);
});
}
void Instance::callFailed(not_null<Call*> call) {
crl::on_main(call, [=] {
destroyCall(call);
});
}
void Instance::callRedial(not_null<Call*> call) {
if (_currentCall.get() == call) {
refreshDhConfig();
}
}
void Instance::groupCallFinished(not_null<GroupCall*> call) {
crl::on_main(call, [=] {
destroyGroupCall(call);
});
}
void Instance::groupCallFailed(not_null<GroupCall*> call) {
crl::on_main(call, [=] {
destroyGroupCall(call);
});
}
not_null<Media::Audio::Track*> Instance::ensureSoundLoaded( not_null<Media::Audio::Track*> Instance::ensureSoundLoaded(
const QString &key) { const QString &key) {
const auto i = _tracks.find(key); const auto i = _tracks.find(key);
@ -132,31 +224,6 @@ void Instance::playSoundOnce(const QString &key) {
ensureSoundLoaded(key)->playOnce(); ensureSoundLoaded(key)->playOnce();
} }
void Instance::callPlaySound(CallSound sound) {
playSoundOnce([&] {
switch (sound) {
case CallSound::Busy: return "call_busy";
case CallSound::Ended: return "call_end";
case CallSound::Connecting: return "call_connect";
}
Unexpected("CallSound in Instance::callPlaySound.");
return "";
}());
}
void Instance::groupCallPlaySound(GroupCallSound sound) {
playSoundOnce([&] {
switch (sound) {
case GroupCallSound::Started: return "group_call_start";
case GroupCallSound::Ended: return "group_call_end";
case GroupCallSound::AllowedToSpeak: return "group_call_allowed";
case GroupCallSound::Connecting: return "group_call_connect";
}
Unexpected("GroupCallSound in Instance::groupCallPlaySound.");
return "";
}());
}
void Instance::destroyCall(not_null<Call*> call) { void Instance::destroyCall(not_null<Call*> call) {
if (_currentCall.get() == call) { if (_currentCall.get() == call) {
_currentCallPanel->closeBeforeDestroy(); _currentCallPanel->closeBeforeDestroy();
@ -174,7 +241,7 @@ void Instance::destroyCall(not_null<Call*> call) {
} }
void Instance::createCall(not_null<UserData*> user, Call::Type type, bool video) { void Instance::createCall(not_null<UserData*> user, Call::Type type, bool video) {
auto call = std::make_unique<Call>(getCallDelegate(), user, type, video); auto call = std::make_unique<Call>(_delegate.get(), user, type, video);
const auto raw = call.get(); const auto raw = call.get();
user->session().account().sessionChanges( user->session().account().sessionChanges(
@ -217,7 +284,7 @@ void Instance::createGroupCall(
destroyCurrentCall(); destroyCurrentCall();
auto call = std::make_unique<GroupCall>( auto call = std::make_unique<GroupCall>(
getGroupCallDelegate(), _delegate.get(),
std::move(info), std::move(info),
inputCall); inputCall);
const auto raw = call.get(); const auto raw = call.get();
@ -237,7 +304,7 @@ void Instance::refreshDhConfig() {
const auto weak = base::make_weak(_currentCall); const auto weak = base::make_weak(_currentCall);
_currentCall->user()->session().api().request(MTPmessages_GetDhConfig( _currentCall->user()->session().api().request(MTPmessages_GetDhConfig(
MTP_int(_dhConfig.version), MTP_int(_cachedDhConfig->version),
MTP_int(MTP::ModExpFirst::kRandomPowerSize) MTP_int(MTP::ModExpFirst::kRandomPowerSize)
)).done([=](const MTPmessages_DhConfig &result) { )).done([=](const MTPmessages_DhConfig &result) {
const auto call = weak.get(); const auto call = weak.get();
@ -249,14 +316,14 @@ void Instance::refreshDhConfig() {
Assert(random.size() == MTP::ModExpFirst::kRandomPowerSize); Assert(random.size() == MTP::ModExpFirst::kRandomPowerSize);
call->start(random); call->start(random);
} else { } else {
callFailed(call); _delegate->callFailed(call);
} }
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
const auto call = weak.get(); const auto call = weak.get();
if (!call) { if (!call) {
return; return;
} }
callFailed(call); _delegate->callFailed(call);
}).send(); }).send();
} }
@ -277,13 +344,13 @@ bytes::const_span Instance::updateDhConfig(
} else if (!validRandom(data.vrandom().v)) { } else if (!validRandom(data.vrandom().v)) {
return {}; return {};
} }
_dhConfig.g = data.vg().v; _cachedDhConfig->g = data.vg().v;
_dhConfig.p = std::move(primeBytes); _cachedDhConfig->p = std::move(primeBytes);
_dhConfig.version = data.vversion().v; _cachedDhConfig->version = data.vversion().v;
return bytes::make_span(data.vrandom().v); return bytes::make_span(data.vrandom().v);
}, [&](const MTPDmessages_dhConfigNotModified &data) }, [&](const MTPDmessages_dhConfigNotModified &data)
-> bytes::const_span { -> bytes::const_span {
if (!_dhConfig.g || _dhConfig.p.empty()) { if (!_cachedDhConfig->g || _cachedDhConfig->p.empty()) {
LOG(("API Error: dhConfigNotModified on zero version.")); LOG(("API Error: dhConfigNotModified on zero version."));
return {}; return {};
} else if (!validRandom(data.vrandom().v)) { } else if (!validRandom(data.vrandom().v)) {
@ -592,22 +659,19 @@ void Instance::requestPermissionOrFail(Platform::PermissionType type, Fn<void()>
} }
} }
std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::callGetVideoCapture() { std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::getVideoCapture(
return getVideoCapture(); QString deviceId) {
} if (deviceId.isEmpty()) {
deviceId = Core::App().settings().callVideoInputDeviceId();
std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::groupCallGetVideoCapture() { }
return getVideoCapture();
}
std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::getVideoCapture() {
if (auto result = _videoCapture.lock()) { if (auto result = _videoCapture.lock()) {
result->switchToDevice(deviceId.toStdString());
return result; return result;
} }
auto result = std::shared_ptr<tgcalls::VideoCaptureInterface>( auto result = std::shared_ptr<tgcalls::VideoCaptureInterface>(
tgcalls::VideoCaptureInterface::Create( tgcalls::VideoCaptureInterface::Create(
tgcalls::StaticThreads::getThreads(), tgcalls::StaticThreads::getThreads(),
Core::App().settings().callVideoInputDeviceId().toStdString())); deviceId.toStdString()));
_videoCapture = result; _videoCapture = result;
return result; return result;
} }

View file

@ -8,9 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "calls/calls_call.h"
#include "calls/group/calls_group_call.h"
#include "calls/group/calls_choose_join_as.h"
namespace Platform { namespace Platform {
enum class PermissionType; enum class PermissionType;
@ -27,17 +24,22 @@ class Session;
namespace Calls::Group { namespace Calls::Group {
struct JoinInfo; struct JoinInfo;
class Panel; class Panel;
class ChooseJoinAsProcess;
} // namespace Calls::Group } // namespace Calls::Group
namespace tgcalls {
class VideoCaptureInterface;
} // namespace tgcalls
namespace Calls { namespace Calls {
class Call;
enum class CallType;
class GroupCall;
class Panel; class Panel;
struct DhConfig;
class Instance class Instance : private base::Subscriber, public base::has_weak_ptr {
: private Call::Delegate
, private GroupCall::Delegate
, private base::Subscriber
, public base::has_weak_ptr {
public: public:
Instance(); Instance();
~Instance(); ~Instance();
@ -69,7 +71,8 @@ public:
bool activateCurrentCall(const QString &joinHash = QString()); bool activateCurrentCall(const QString &joinHash = QString());
bool minimizeCurrentActiveCall(); bool minimizeCurrentActiveCall();
bool closeCurrentActiveCall(); bool closeCurrentActiveCall();
std::shared_ptr<tgcalls::VideoCaptureInterface> getVideoCapture(); [[nodiscard]] auto getVideoCapture(QString deviceId = QString())
-> std::shared_ptr<tgcalls::VideoCaptureInterface>;
void requestPermissionsOrFail(Fn<void()> onSuccess, bool video = true); void requestPermissionsOrFail(Fn<void()> onSuccess, bool video = true);
void setCurrentAudioDevice(bool input, const QString &deviceId); void setCurrentAudioDevice(bool input, const QString &deviceId);
@ -77,44 +80,13 @@ public:
[[nodiscard]] bool isQuitPrevent(); [[nodiscard]] bool isQuitPrevent();
private: private:
using CallSound = Call::Delegate::CallSound; class Delegate;
using GroupCallSound = GroupCall::Delegate::GroupCallSound; friend class Delegate;
[[nodiscard]] not_null<Call::Delegate*> getCallDelegate() {
return static_cast<Call::Delegate*>(this);
}
[[nodiscard]] not_null<GroupCall::Delegate*> getGroupCallDelegate() {
return static_cast<GroupCall::Delegate*>(this);
}
[[nodiscard]] DhConfig getDhConfig() const override {
return _dhConfig;
}
not_null<Media::Audio::Track*> ensureSoundLoaded(const QString &key); not_null<Media::Audio::Track*> ensureSoundLoaded(const QString &key);
void playSoundOnce(const QString &key); void playSoundOnce(const QString &key);
void callFinished(not_null<Call*> call) override; void createCall(not_null<UserData*> user, CallType type, bool video);
void callFailed(not_null<Call*> call) override;
void callRedial(not_null<Call*> call) override;
void callRequestPermissionsOrFail(
Fn<void()> onSuccess,
bool video) override {
requestPermissionsOrFail(std::move(onSuccess), video);
}
void callPlaySound(CallSound sound) override;
auto callGetVideoCapture()
->std::shared_ptr<tgcalls::VideoCaptureInterface> override;
void groupCallFinished(not_null<GroupCall*> call) override;
void groupCallFailed(not_null<GroupCall*> call) override;
void groupCallRequestPermissionsOrFail(Fn<void()> onSuccess) override {
requestPermissionsOrFail(std::move(onSuccess), false);
}
void groupCallPlaySound(GroupCallSound sound) override;
auto groupCallGetVideoCapture()
->std::shared_ptr<tgcalls::VideoCaptureInterface> override;
void createCall(not_null<UserData*> user, Call::Type type, bool video);
void destroyCall(not_null<Call*> call); void destroyCall(not_null<Call*> call);
void createGroupCall( void createGroupCall(
@ -141,7 +113,8 @@ private:
not_null<Main::Session*> session, not_null<Main::Session*> session,
const MTPUpdate &update); const MTPUpdate &update);
DhConfig _dhConfig; const std::unique_ptr<Delegate> _delegate;
const std::unique_ptr<DhConfig> _cachedDhConfig;
crl::time _lastServerConfigUpdateTime = 0; crl::time _lastServerConfigUpdateTime = 0;
base::weak_ptr<Main::Session> _serverConfigRequestSession; base::weak_ptr<Main::Session> _serverConfigRequestSession;
@ -157,7 +130,7 @@ private:
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks; base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
Group::ChooseJoinAsProcess _chooseJoinAs; const std::unique_ptr<Group::ChooseJoinAsProcess> _chooseJoinAs;
}; };

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/calls_call.h" #include "calls/calls_call.h"
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "calls/calls_signal_bars.h" #include "calls/calls_signal_bars.h"
#include "calls/group/calls_group_call.h"
#include "calls/group/calls_group_menu.h" // Group::LeaveBox. #include "calls/group/calls_group_menu.h" // Group::LeaveBox.
#include "history/view/history_view_group_call_tracker.h" // ContentByCall. #include "history/view/history_view_group_call_tracker.h" // ContentByCall.
#include "data/data_user.h" #include "data/data_user.h"

View file

@ -313,8 +313,8 @@ GroupCall::GroupCall(
, _joinHash(info.joinHash) , _joinHash(info.joinHash)
, _id(inputCall.c_inputGroupCall().vid().v) , _id(inputCall.c_inputGroupCall().vid().v)
, _scheduleDate(info.scheduleDate) , _scheduleDate(info.scheduleDate)
, _videoOutgoing(std::make_unique<Webrtc::VideoTrack>( , _videoOutgoing(
Webrtc::VideoState::Inactive)) std::make_unique<Webrtc::VideoTrack>(Webrtc::VideoState::Inactive))
, _lastSpokeCheckTimer([=] { checkLastSpoke(); }) , _lastSpokeCheckTimer([=] { checkLastSpoke(); })
, _checkJoinedTimer([=] { checkJoined(); }) , _checkJoinedTimer([=] { checkJoined(); })
, _pushToTalkCancelTimer([=] { pushToTalkCancel(); }) , _pushToTalkCancelTimer([=] { pushToTalkCancel(); })
@ -402,6 +402,7 @@ void GroupCall::switchToCamera() {
return; return;
} }
_videoDeviceId = _videoInputId; _videoDeviceId = _videoInputId;
if (_videoOutgoing)
_videoCapture->switchToDevice(_videoDeviceId.toStdString()); _videoCapture->switchToDevice(_videoDeviceId.toStdString());
} }
@ -1366,10 +1367,42 @@ void GroupCall::setupMediaDevices() {
} }
void GroupCall::setupOutgoingVideo() { void GroupCall::setupOutgoingVideo() {
_videoCapture = _delegate->groupCallGetVideoCapture();
_videoOutgoing->setState(Webrtc::VideoState::Active);
_videoCapture->setOutput(_videoOutgoing->sink());
_videoDeviceId = _videoInputId; _videoDeviceId = _videoInputId;
static const auto hasDevices = [] {
return !Webrtc::GetVideoInputList().empty();
};
const auto started = _videoOutgoing->state();
if (!hasDevices()) {
_videoOutgoing->setState(Webrtc::VideoState::Inactive);
}
_videoOutgoing->stateValue(
) | rpl::start_with_next([=](Webrtc::VideoState state) {
if (state != Webrtc::VideoState::Inactive && !hasDevices()) {
//_errors.fire({ ErrorType::NoCamera }); // #TODO videochats
_videoOutgoing->setState(Webrtc::VideoState::Inactive);
//} else if (state != Webrtc::VideoState::Inactive
// && _instance
// && !_instance->supportsVideo()) {
// _errors.fire({ ErrorType::NotVideoCall });
// _videoOutgoing->setState(Webrtc::VideoState::Inactive);
} else if (state != Webrtc::VideoState::Inactive) {
// Paused not supported right now.
Assert(state == Webrtc::VideoState::Active);
if (!_videoCapture) {
_videoCapture = _delegate->groupCallGetVideoCapture(
_videoDeviceId);
_videoCapture->setOutput(_videoOutgoing->sink());
} else {
_videoCapture->switchToDevice(_videoDeviceId.toStdString());
}
if (_instance) {
_instance->setVideoCapture(_videoCapture, nullptr);
}
_videoCapture->setState(tgcalls::VideoState::Active);
} else if (_videoCapture) {
_videoCapture->setState(tgcalls::VideoState::Inactive);
}
}, _lifetime);
} }
void GroupCall::changeTitle(const QString &title) { void GroupCall::changeTitle(const QString &title) {
@ -1424,6 +1457,7 @@ void GroupCall::ensureControllerCreated() {
const auto weak = base::make_weak(this); const auto weak = base::make_weak(this);
const auto myLevel = std::make_shared<tgcalls::GroupLevelValue>(); const auto myLevel = std::make_shared<tgcalls::GroupLevelValue>();
_videoCall = true;
tgcalls::GroupInstanceDescriptor descriptor = { tgcalls::GroupInstanceDescriptor descriptor = {
.threads = tgcalls::StaticThreads::getThreads(), .threads = tgcalls::StaticThreads::getThreads(),
.config = tgcalls::GroupConfig{ .config = tgcalls::GroupConfig{
@ -1451,13 +1485,10 @@ void GroupCall::ensureControllerCreated() {
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator( .createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
settings.callAudioBackend()), settings.callAudioBackend()),
.videoCapture = _videoCapture, .videoCapture = _videoCapture,
//.getVideoSource = [=] {
// return _videoCapture->
//},
.incomingVideoSourcesUpdated = [=]( .incomingVideoSourcesUpdated = [=](
const std::vector<uint32_t> &ssrcs) { const std::vector<uint32_t> &ssrcs) {
crl::on_main(weak, [=] { crl::on_main(weak, [=] {
showVideoStreams(ssrcs); setVideoStreams(ssrcs);
}); });
}, },
.participantDescriptionsRequired = [=]( .participantDescriptionsRequired = [=](
@ -1609,9 +1640,53 @@ void GroupCall::requestParticipantsInformation(
addPreparedParticipants(); addPreparedParticipants();
} }
void GroupCall::showVideoStreams(const std::vector<std::uint32_t> &ssrcs) { void GroupCall::setVideoStreams(const std::vector<std::uint32_t> &ssrcs) {
const auto large = _videoStreamLarge.current();
auto newLarge = large;
if (large && !ranges::contains(ssrcs, large)) {
newLarge = 0;
_videoStreamPinned = 0;
}
auto lastSpokeVoice = crl::time(0);
auto lastSpokeVoiceSsrc = uint32(0);
auto lastSpokeAnything = crl::time(0);
auto lastSpokeAnythingSsrc = uint32(0);
auto removed = _videoStreamSsrcs;
for (const auto ssrc : ssrcs) { for (const auto ssrc : ssrcs) {
_videoStreamUpdated.fire_copy(ssrc); const auto i = removed.find(ssrc);
if (i != end(removed)) {
removed.erase(i);
} else {
_videoStreamSsrcs.emplace(ssrc);
_streamsVideoUpdated.fire({ ssrc, true });
}
if (!newLarge) {
const auto j = _lastSpoke.find(ssrc);
if (j != end(_lastSpoke)) {
if (!lastSpokeVoiceSsrc
|| lastSpokeVoice < j->second.voice) {
lastSpokeVoiceSsrc = ssrc;
lastSpokeVoice = j->second.voice;
}
if (!lastSpokeAnythingSsrc
|| lastSpokeAnything < j->second.anything) {
lastSpokeAnythingSsrc = ssrc;
lastSpokeAnything = j->second.anything;
}
}
}
}
if (!newLarge) {
_videoStreamLarge = lastSpokeVoiceSsrc
? lastSpokeVoiceSsrc
: lastSpokeAnythingSsrc
? lastSpokeAnythingSsrc
: ssrcs.empty()
? 0
: ssrcs.front();
}
for (const auto ssrc : removed) {
_streamsVideoUpdated.fire({ ssrc, false });
} }
} }
@ -2035,45 +2110,6 @@ auto GroupCall::otherParticipantStateValue() const
return _otherParticipantStateValue.events(); return _otherParticipantStateValue.events();
} }
//void GroupCall::setAudioVolume(bool input, float level) {
// if (_instance) {
// if (input) {
// _instance->setInputVolume(level);
// } else {
// _instance->setOutputVolume(level);
// }
// }
//}
void GroupCall::setAudioDuckingEnabled(bool enabled) {
if (_instance) {
//_instance->setAudioOutputDuckingEnabled(enabled);
}
}
void GroupCall::handleRequestError(const MTP::Error &error) {
//if (error.type() == qstr("USER_PRIVACY_RESTRICTED")) {
// Ui::show(Box<InformBox>(tr::lng_call_error_not_available(tr::now, lt_user, _user->name)));
//} else if (error.type() == qstr("PARTICIPANT_VERSION_OUTDATED")) {
// Ui::show(Box<InformBox>(tr::lng_call_error_outdated(tr::now, lt_user, _user->name)));
//} else if (error.type() == qstr("CALL_PROTOCOL_LAYER_INVALID")) {
// Ui::show(Box<InformBox>(Lang::Hard::CallErrorIncompatible().replace("{user}", _user->name)));
//}
//finish(FinishType::Failed);
}
void GroupCall::handleControllerError(const QString &error) {
if (error == u"ERROR_INCOMPATIBLE"_q) {
//Ui::show(Box<InformBox>(
// Lang::Hard::CallErrorIncompatible().replace(
// "{user}",
// _user->name)));
} else if (error == u"ERROR_AUDIO_IO"_q) {
//Ui::show(Box<InformBox>(tr::lng_call_error_audio_io(tr::now)));
}
//finish(FinishType::Failed);
}
MTPInputGroupCall GroupCall::inputCall() const { MTPInputGroupCall GroupCall::inputCall() const {
Expects(_id != 0); Expects(_id != 0);
@ -2084,9 +2120,6 @@ MTPInputGroupCall GroupCall::inputCall() const {
void GroupCall::destroyController() { void GroupCall::destroyController() {
if (_instance) { if (_instance) {
//_instance->stop([](tgcalls::FinalState) {
//});
DEBUG_LOG(("Call Info: Destroying call controller..")); DEBUG_LOG(("Call Info: Destroying call controller.."));
_instance.reset(); _instance.reset();
DEBUG_LOG(("Call Info: Call controller destroyed.")); DEBUG_LOG(("Call Info: Call controller destroyed."));

View file

@ -74,6 +74,11 @@ struct LevelUpdate {
bool me = false; bool me = false;
}; };
struct StreamsVideoUpdate {
uint32 ssrc = 0;
bool streams = false;
};
struct VideoParams; struct VideoParams;
[[nodiscard]] std::shared_ptr<VideoParams> ParseVideoParams( [[nodiscard]] std::shared_ptr<VideoParams> ParseVideoParams(
@ -100,7 +105,7 @@ public:
Ended, Ended,
}; };
virtual void groupCallPlaySound(GroupCallSound sound) = 0; virtual void groupCallPlaySound(GroupCallSound sound) = 0;
virtual auto groupCallGetVideoCapture() virtual auto groupCallGetVideoCapture(const QString &deviceId)
-> std::shared_ptr<tgcalls::VideoCaptureInterface> = 0; -> std::shared_ptr<tgcalls::VideoCaptureInterface> = 0;
}; };
@ -158,6 +163,13 @@ public:
return _muted.value(); return _muted.value();
} }
[[nodiscard]] bool videoCall() const {
return _videoCall.current();
}
[[nodiscard]] rpl::producer<bool> videoCallValue() const {
return _videoCall.value();
}
[[nodiscard]] auto otherParticipantStateValue() const [[nodiscard]] auto otherParticipantStateValue() const
-> rpl::producer<Group::ParticipantState>; -> rpl::producer<Group::ParticipantState>;
@ -194,8 +206,15 @@ public:
[[nodiscard]] rpl::producer<LevelUpdate> levelUpdates() const { [[nodiscard]] rpl::producer<LevelUpdate> levelUpdates() const {
return _levelUpdates.events(); return _levelUpdates.events();
} }
[[nodiscard]] rpl::producer<uint32> videoStreamUpdated() const { [[nodiscard]] auto streamsVideoUpdates() const
return _videoStreamUpdated.events(); -> rpl::producer<StreamsVideoUpdate> {
return _streamsVideoUpdated.events();
}
[[nodiscard]] uint32 videoStreamLarge() const {
return _videoStreamLarge.current();
}
[[nodiscard]] rpl::producer<uint32> videoStreamLargeValue() const {
return _videoStreamLarge.value();
} }
[[nodiscard]] rpl::producer<Group::RejoinEvent> rejoinEvents() const { [[nodiscard]] rpl::producer<Group::RejoinEvent> rejoinEvents() const {
return _rejoinEvents.events(); return _rejoinEvents.events();
@ -213,8 +232,6 @@ public:
bool isScreenSharing() const; bool isScreenSharing() const;
void switchToCamera(); void switchToCamera();
void switchToScreenSharing(const QString &uniqueId); void switchToScreenSharing(const QString &uniqueId);
//void setAudioVolume(bool input, float level);
void setAudioDuckingEnabled(bool enabled);
void toggleMute(const Group::MuteRequest &data); void toggleMute(const Group::MuteRequest &data);
void changeVolume(const Group::VolumeRequest &data); void changeVolume(const Group::VolumeRequest &data);
@ -264,8 +281,6 @@ private:
void handlePossibleDiscarded(const MTPDgroupCallDiscarded &data); void handlePossibleDiscarded(const MTPDgroupCallDiscarded &data);
void handleUpdate(const MTPDupdateGroupCall &data); void handleUpdate(const MTPDupdateGroupCall &data);
void handleUpdate(const MTPDupdateGroupCallParticipants &data); void handleUpdate(const MTPDupdateGroupCallParticipants &data);
void handleRequestError(const MTP::Error &error);
void handleControllerError(const QString &error);
void ensureControllerCreated(); void ensureControllerCreated();
void destroyController(); void destroyController();
@ -304,7 +319,7 @@ private:
const Data::GroupCallParticipant &participant); const Data::GroupCallParticipant &participant);
void addPreparedParticipants(); void addPreparedParticipants();
void addPreparedParticipantsDelayed(); void addPreparedParticipantsDelayed();
void showVideoStreams(const std::vector<std::uint32_t> &ssrcs); void setVideoStreams(const std::vector<std::uint32_t> &ssrcs);
void editParticipant( void editParticipant(
not_null<PeerData*> participantPeer, not_null<PeerData*> participantPeer,
@ -347,6 +362,7 @@ private:
QString _joinHash; QString _joinHash;
rpl::variable<MuteState> _muted = MuteState::Muted; rpl::variable<MuteState> _muted = MuteState::Muted;
rpl::variable<bool> _videoCall = false;
bool _initialMuteStateSent = false; bool _initialMuteStateSent = false;
bool _acceptFields = false; bool _acceptFields = false;
@ -365,7 +381,10 @@ private:
std::shared_ptr<tgcalls::VideoCaptureInterface> _videoCapture; std::shared_ptr<tgcalls::VideoCaptureInterface> _videoCapture;
const std::unique_ptr<Webrtc::VideoTrack> _videoOutgoing; const std::unique_ptr<Webrtc::VideoTrack> _videoOutgoing;
rpl::event_stream<LevelUpdate> _levelUpdates; rpl::event_stream<LevelUpdate> _levelUpdates;
rpl::event_stream<uint32> _videoStreamUpdated; rpl::event_stream<StreamsVideoUpdate> _streamsVideoUpdated;
base::flat_set<uint32> _videoStreamSsrcs;
rpl::variable<uint32> _videoStreamLarge = 0;
uint32 _videoStreamPinned = 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;

View file

@ -47,4 +47,9 @@ struct JoinInfo {
TimeId scheduleDate = 0; TimeId scheduleDate = 0;
}; };
enum class PanelMode {
Default,
Wide,
};
} // namespace Calls::Group } // namespace Calls::Group

View file

@ -143,6 +143,7 @@ public:
} }
[[nodiscard]] not_null<Webrtc::VideoTrack*> createVideoTrack(); [[nodiscard]] not_null<Webrtc::VideoTrack*> createVideoTrack();
void clearVideoTrack();
void setVideoTrack(not_null<Webrtc::VideoTrack*> track); void setVideoTrack(not_null<Webrtc::VideoTrack*> track);
void addActionRipple(QPoint point, Fn<void()> updateCallback) override; void addActionRipple(QPoint point, Fn<void()> updateCallback) override;
@ -352,12 +353,14 @@ private:
not_null<Row*> row, not_null<Row*> row,
uint64 raiseHandRating) const; uint64 raiseHandRating) const;
Row *findRow(not_null<PeerData*> participantPeer) const; Row *findRow(not_null<PeerData*> participantPeer) const;
Row *findRow(uint32 audioSsrc) const;
void appendInvitedUsers(); void appendInvitedUsers();
void scheduleRaisedHandStatusRemove(); void scheduleRaisedHandStatusRemove();
const not_null<GroupCall*> _call; const not_null<GroupCall*> _call;
not_null<PeerData*> _peer; not_null<PeerData*> _peer;
uint32 _largeSsrc = 0;
bool _prepared = false; bool _prepared = false;
rpl::event_stream<MuteRequest> _toggleMuteRequests; rpl::event_stream<MuteRequest> _toggleMuteRequests;
@ -926,6 +929,13 @@ not_null<Webrtc::VideoTrack*> Row::createVideoTrack() {
return _videoTrack.get(); return _videoTrack.get();
} }
void Row::clearVideoTrack() {
_videoTrackLifetime.destroy();
_videoTrackShown = nullptr;
_videoTrack = nullptr;
_delegate->rowUpdateRow(this);
}
void Row::setVideoTrack(not_null<Webrtc::VideoTrack*> track) { void Row::setVideoTrack(not_null<Webrtc::VideoTrack*> track) {
_videoTrackLifetime.destroy(); _videoTrackLifetime.destroy();
_videoTrackShown = track; _videoTrackShown = track;
@ -1043,17 +1053,29 @@ void MembersController::setupListChangeViewers() {
} }
}, _lifetime); }, _lifetime);
_call->videoStreamUpdated(
) | rpl::start_with_next([=](uint32 ssrc) { _call->videoStreamLargeValue(
const auto real = _call->lookupReal(); ) | rpl::filter([=](uint32 largeSsrc) {
const auto participantPeer = real return (_largeSsrc != largeSsrc);
? real->participantPeerByAudioSsrc(ssrc) }) | rpl::start_with_next([=](uint32 largeSsrc) {
: nullptr; if (const auto row = findRow(_largeSsrc)) {
const auto row = participantPeer _call->addVideoOutput(_largeSsrc, row->createVideoTrack());
? findRow(participantPeer) }
: nullptr; _largeSsrc = largeSsrc;
if (row) { if (const auto row = findRow(_largeSsrc)) {
_call->addVideoOutput(ssrc, row->createVideoTrack()); row->clearVideoTrack();
}
}, _lifetime);
_call->streamsVideoUpdates(
) | rpl::start_with_next([=](StreamsVideoUpdate update) {
Assert(update.ssrc != _largeSsrc);
if (const auto row = findRow(update.ssrc)) {
if (update.streams) {
_call->addVideoOutput(update.ssrc, row->createVideoTrack());
} else {
row->clearVideoTrack();
}
} }
}, _lifetime); }, _lifetime);
@ -1345,8 +1367,6 @@ void MembersController::updateRow(
} }
if (isMe(row->peer())) { if (isMe(row->peer())) {
row->setVideoTrack(_call->outgoingVideoTrack()); row->setVideoTrack(_call->outgoingVideoTrack());
} else if (nowSsrc) {
_call->addVideoOutput(nowSsrc, row->createVideoTrack());
} }
} }
const auto nowNoSounding = _soundingRowBySsrc.empty(); const auto nowNoSounding = _soundingRowBySsrc.empty();
@ -1378,6 +1398,17 @@ Row *MembersController::findRow(not_null<PeerData*> participantPeer) const {
delegate()->peerListFindRow(participantPeer->id.value)); delegate()->peerListFindRow(participantPeer->id.value));
} }
Row *MembersController::findRow(uint32 audioSsrc) const {
if (!audioSsrc) {
return nullptr;
}
const auto real = _call->lookupReal();
const auto participantPeer = real
? real->participantPeerByAudioSsrc(audioSsrc)
: nullptr;
return participantPeer ? findRow(participantPeer) : nullptr;
}
Main::Session &MembersController::session() const { Main::Session &MembersController::session() const {
return _call->peer()->session(); return _call->peer()->session();
} }
@ -1943,8 +1974,11 @@ int Members::desiredHeight() const {
return 0; return 0;
}(); }();
const auto use = std::max(count, _list->fullRowsCount()); const auto use = std::max(count, _list->fullRowsCount());
const auto single = (_mode == PanelMode::Wide)
? (st::groupCallNarrowSize.height() + st::groupCallNarrowRowSkip)
: st::groupCallMembersList.item.height;
return top return top
+ (use * st::groupCallMembersList.item.height) + (use * single)
+ (use ? st::lineWidth : 0); + (use ? st::lineWidth : 0);
} }
@ -2008,6 +2042,16 @@ void Members::setupAddMember(not_null<GroupCall*> call) {
}, lifetime()); }, lifetime());
} }
void Members::setMode(PanelMode mode) {
if (_mode == mode) {
return;
}
_mode = mode;
_list->setMode((_mode == PanelMode::Wide)
? PeerListContent::Mode::Custom
: PeerListContent::Mode::Default);
}
rpl::producer<int> Members::fullCountValue() const { rpl::producer<int> Members::fullCountValue() const {
return static_cast<MembersController*>( return static_cast<MembersController*>(
_listController.get())->fullCountValue(); _listController.get())->fullCountValue();

View file

@ -26,6 +26,7 @@ namespace Calls::Group {
struct VolumeRequest; struct VolumeRequest;
struct MuteRequest; struct MuteRequest;
enum class PanelMode;
class Members final class Members final
: public Ui::RpWidget : public Ui::RpWidget
@ -48,6 +49,8 @@ public:
return _addMemberRequests.events(); return _addMemberRequests.events();
} }
void setMode(PanelMode mode);
private: private:
using ListWidget = PeerListContent; using ListWidget = PeerListContent;
@ -76,6 +79,7 @@ private:
void updateControlsGeometry(); void updateControlsGeometry();
const not_null<GroupCall*> _call; const not_null<GroupCall*> _call;
PanelMode _mode = PanelMode();
object_ptr<Ui::ScrollArea> _scroll; object_ptr<Ui::ScrollArea> _scroll;
std::unique_ptr<PeerListController> _listController; std::unique_ptr<PeerListController> _listController;
object_ptr<Ui::SettingsButton> _addMember = { nullptr }; object_ptr<Ui::SettingsButton> _addMember = { nullptr };

View file

@ -525,6 +525,11 @@ void Panel::initWindow() {
? (Flag::Move | Flag::Maximize) ? (Flag::Move | Flag::Maximize)
: Flag::None; : Flag::None;
}); });
_call->videoCallValue(
) | rpl::start_with_next([=] {
updateMode();
}, _window->lifetime());
} }
void Panel::initWidget() { void Panel::initWidget() {
@ -536,8 +541,10 @@ void Panel::initWidget() {
}, widget()->lifetime()); }, widget()->lifetime());
widget()->sizeValue( widget()->sizeValue(
) | rpl::skip(1) | rpl::start_with_next([=] { ) | rpl::skip(1) | rpl::start_with_next([=](QSize size) {
updateControlsGeometry(); if (!updateMode()) {
updateControlsGeometry();
}
// title geometry depends on _controls->geometry, // title geometry depends on _controls->geometry,
// which is not updated here yet. // which is not updated here yet.
@ -1384,6 +1391,21 @@ QRect Panel::computeTitleRect() const {
#endif // !Q_OS_MAC #endif // !Q_OS_MAC
} }
bool Panel::updateMode() {
const auto wide = _call->videoCall()
&& (widget()->width() >= st::groupCallWideModeWidthMin);
const auto mode = wide ? PanelMode::Wide : PanelMode::Default;
if (_mode == mode) {
return false;
}
_mode = mode;
if (_members) {
_members->setMode(mode);
}
updateControlsGeometry();
return true;
}
void Panel::updateControlsGeometry() { void Panel::updateControlsGeometry() {
if (widget()->size().isEmpty() || (!_settings && !_share)) { if (widget()->size().isEmpty() || (!_settings && !_share)) {
return; return;
@ -1434,27 +1456,35 @@ void Panel::updateMembersGeometry() {
if (!_members) { if (!_members) {
return; return;
} }
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
const auto membersTop = st::groupCallMembersTop;
const auto availableHeight = muteTop
- membersTop
- st::groupCallMembersMargin.bottom();
const auto desiredHeight = _members->desiredHeight(); const auto desiredHeight = _members->desiredHeight();
const auto membersWidthAvailable = widget()->width() if (_mode == PanelMode::Wide) {
- st::groupCallMembersMargin.left() _members->setGeometry(
- st::groupCallMembersMargin.right(); st::groupCallNarrowSkip,
const auto membersWidthMin = st::groupCallWidth 0,
- st::groupCallMembersMargin.left() st::groupCallNarrowSize.width(),
- st::groupCallMembersMargin.right(); std::min(desiredHeight, widget()->height()));
const auto membersWidth = std::clamp( } else {
membersWidthAvailable, const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
membersWidthMin, const auto membersTop = st::groupCallMembersTop;
st::groupCallMembersWidthMax); const auto availableHeight = muteTop
_members->setGeometry( - membersTop
(widget()->width() - membersWidth) / 2, - st::groupCallMembersMargin.bottom();
membersTop, const auto membersWidthAvailable = widget()->width()
membersWidth, - st::groupCallMembersMargin.left()
std::min(desiredHeight, availableHeight)); - st::groupCallMembersMargin.right();
const auto membersWidthMin = st::groupCallWidth
- st::groupCallMembersMargin.left()
- st::groupCallMembersMargin.right();
const auto membersWidth = std::clamp(
membersWidthAvailable,
membersWidthMin,
st::groupCallMembersWidthMax);
_members->setGeometry(
(widget()->width() - membersWidth) / 2,
membersTop,
membersWidth,
std::min(desiredHeight, availableHeight));
}
} }
void Panel::refreshTitle() { void Panel::refreshTitle() {

View file

@ -53,6 +53,7 @@ struct CallBodyLayout;
namespace Calls::Group { namespace Calls::Group {
class Members; class Members;
enum class PanelMode;
class Panel final : private Ui::DesktopCapture::ChooseSourceDelegate { class Panel final : private Ui::DesktopCapture::ChooseSourceDelegate {
public: public:
@ -88,6 +89,7 @@ private:
bool handleClose(); bool handleClose();
void startScheduledNow(); void startScheduledNow();
bool updateMode();
void updateControlsGeometry(); void updateControlsGeometry();
void updateMembersGeometry(); void updateMembersGeometry();
void showControls(); void showControls();
@ -118,6 +120,7 @@ private:
const std::unique_ptr<Ui::Window> _window; const std::unique_ptr<Ui::Window> _window;
const std::unique_ptr<Ui::LayerManager> _layerBg; const std::unique_ptr<Ui::LayerManager> _layerBg;
PanelMode _mode = PanelMode();
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
std::unique_ptr<Ui::Platform::TitleControls> _controls; std::unique_ptr<Ui::Platform::TitleControls> _controls;

View file

@ -93,8 +93,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/changelogs.h" #include "core/changelogs.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "calls/calls_call.h"
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "calls/calls_top_bar.h" #include "calls/calls_top_bar.h"
#include "calls/group/calls_group_call.h"
#include "export/export_settings.h" #include "export/export_settings.h"
#include "export/export_manager.h" #include "export/export_manager.h"
#include "export/view/export_view_top_bar.h" #include "export/view/export_view_top_bar.h"

View file

@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "calls/calls_call.h"
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "calls/calls_video_bubble.h" #include "calls/calls_video_bubble.h"
#include "webrtc/webrtc_media_devices.h" #include "webrtc/webrtc_media_devices.h"
@ -250,40 +251,6 @@ void Calls::setupContent() {
AddSkip(content); AddSkip(content);
AddSubsectionTitle(content, tr::lng_settings_call_section_other()); AddSubsectionTitle(content, tr::lng_settings_call_section_other());
//#if defined Q_OS_MAC && !defined OS_MAC_STORE
// AddButton(
// content,
// tr::lng_settings_call_audio_ducking(),
// st::settingsButton
// )->toggleOn(
// rpl::single(settings.callAudioDuckingEnabled())
// )->toggledValue() | rpl::filter([](bool enabled) {
// return (enabled != Core::App().settings().callAudioDuckingEnabled());
// }) | rpl::start_with_next([=](bool enabled) {
// Core::App().settings().setCallAudioDuckingEnabled(enabled);
// Core::App().saveSettingsDelayed();
// if (const auto call = Core::App().calls().currentCall()) {
// call->setAudioDuckingEnabled(enabled);
// }
// }, content->lifetime());
//#endif // Q_OS_MAC && !OS_MAC_STORE
//const auto backend = [&]() -> QString {
// using namespace Webrtc;
// switch (settings.callAudioBackend()) {
// case Backend::OpenAL: return "OpenAL";
// case Backend::ADM: return "WebRTC ADM";
// case Backend::ADM2: return "WebRTC ADM2";
// }
// Unexpected("Value in backend.");
//}();
//AddButton(
// content,
// rpl::single("Call audio backend: " + backend),
// st::settingsButton
//)->addClickHandler([] {
// Ui::show(ChooseAudioBackendBox());
//});
AddButton( AddButton(
content, content,
tr::lng_settings_call_accept_calls(), tr::lng_settings_call_accept_calls(),

View file

@ -42,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h" #include "ui/toasts/common_toasts.h"
#include "calls/calls_instance.h" // Core::App().calls().inCall(). #include "calls/calls_instance.h" // Core::App().calls().inCall().
#include "calls/group/calls_group_call.h"
#include "ui/boxes/calendar_box.h" #include "ui/boxes/calendar_box.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "mainwidget.h" #include "mainwidget.h"