mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Separate Call/GroupCall delegates and Instance.
This commit is contained in:
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 |
BIN
Telegram/Resources/icons/calls/calls_settings.png
Normal file
BIN
Telegram/Resources/icons/calls/calls_settings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 756 B |
BIN
Telegram/Resources/icons/calls/calls_settings@2x.png
Normal file
BIN
Telegram/Resources/icons/calls/calls_settings@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
Telegram/Resources/icons/calls/calls_settings@3x.png
Normal file
BIN
Telegram/Resources/icons/calls/calls_settings@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
|
@ -1107,7 +1107,9 @@ void PeerListContent::paintEvent(QPaintEvent *e) {
|
|||
Painter p(this);
|
||||
|
||||
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();
|
||||
auto repaintAfterMin = repaintByStatusAfter;
|
||||
|
|
|
@ -736,7 +736,7 @@ groupCallMemberRaisedHand: icon {{ "calls/group_calls_raised_hand", groupCallMem
|
|||
|
||||
groupCallSettingsInner: IconButton(callButton) {
|
||||
iconPosition: point(-1px, 22px);
|
||||
icon: icon {{ "calls/call_settings", groupCallIconFg }};
|
||||
icon: icon {{ "calls/calls_settings", groupCallIconFg }};
|
||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||
color: callMuteRipple;
|
||||
}
|
||||
|
@ -1022,3 +1022,5 @@ desktopCaptureSourceSkip: 12px;
|
|||
groupCallNarrowSkip: 9px;
|
||||
groupCallNarrowRowSkip: 8px;
|
||||
groupCallNarrowSize: size(90px, 90px);
|
||||
groupCallWideModeWidthMin: 800px;
|
||||
groupCallWideModeSize: size(960px, 520px);
|
||||
|
|
|
@ -161,8 +161,12 @@ Call::Call(
|
|||
, _user(user)
|
||||
, _api(&_user->session().mtp())
|
||||
, _type(type)
|
||||
, _videoIncoming(std::make_unique<Webrtc::VideoTrack>(StartVideoState(video)))
|
||||
, _videoOutgoing(std::make_unique<Webrtc::VideoTrack>(StartVideoState(video))) {
|
||||
, _videoIncoming(
|
||||
std::make_unique<Webrtc::VideoTrack>(
|
||||
StartVideoState(video)))
|
||||
, _videoOutgoing(
|
||||
std::make_unique<Webrtc::VideoTrack>(
|
||||
StartVideoState(video))) {
|
||||
_discardByTimeoutTimer.setCallback([=] { hangup(); });
|
||||
|
||||
if (_type == Type::Outgoing) {
|
||||
|
|
|
@ -53,6 +53,11 @@ struct Error {
|
|||
QString details;
|
||||
};
|
||||
|
||||
enum class CallType {
|
||||
Incoming,
|
||||
Outgoing,
|
||||
};
|
||||
|
||||
class Call : public base::has_weak_ptr {
|
||||
public:
|
||||
class Delegate {
|
||||
|
@ -81,11 +86,12 @@ public:
|
|||
|
||||
static constexpr auto kSoundSampleMs = 100;
|
||||
|
||||
enum class Type {
|
||||
Incoming,
|
||||
Outgoing,
|
||||
};
|
||||
Call(not_null<Delegate*> delegate, not_null<UserData*> user, Type type, bool video);
|
||||
using Type = CallType;
|
||||
Call(
|
||||
not_null<Delegate*> delegate,
|
||||
not_null<UserData*> user,
|
||||
Type type,
|
||||
bool video);
|
||||
|
||||
[[nodiscard]] Type type() const {
|
||||
return _type;
|
||||
|
|
|
@ -7,7 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "calls/calls_instance.h"
|
||||
|
||||
#include "calls/calls_call.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 "core/application.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -41,9 +44,128 @@ namespace {
|
|||
|
||||
constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * crl::time(1000);
|
||||
|
||||
using CallSound = Call::Delegate::CallSound;
|
||||
using GroupCallSound = GroupCall::Delegate::GroupCallSound;
|
||||
|
||||
} // 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;
|
||||
|
||||
|
@ -72,7 +194,7 @@ void Instance::startOrJoinGroupCall(
|
|||
: peer->groupCall()
|
||||
? Group::ChooseJoinAsProcess::Context::Join
|
||||
: 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);
|
||||
}, [=](QString 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(
|
||||
const QString &key) {
|
||||
const auto i = _tracks.find(key);
|
||||
|
@ -132,31 +224,6 @@ void Instance::playSoundOnce(const QString &key) {
|
|||
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) {
|
||||
if (_currentCall.get() == call) {
|
||||
_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) {
|
||||
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();
|
||||
|
||||
user->session().account().sessionChanges(
|
||||
|
@ -217,7 +284,7 @@ void Instance::createGroupCall(
|
|||
destroyCurrentCall();
|
||||
|
||||
auto call = std::make_unique<GroupCall>(
|
||||
getGroupCallDelegate(),
|
||||
_delegate.get(),
|
||||
std::move(info),
|
||||
inputCall);
|
||||
const auto raw = call.get();
|
||||
|
@ -237,7 +304,7 @@ void Instance::refreshDhConfig() {
|
|||
|
||||
const auto weak = base::make_weak(_currentCall);
|
||||
_currentCall->user()->session().api().request(MTPmessages_GetDhConfig(
|
||||
MTP_int(_dhConfig.version),
|
||||
MTP_int(_cachedDhConfig->version),
|
||||
MTP_int(MTP::ModExpFirst::kRandomPowerSize)
|
||||
)).done([=](const MTPmessages_DhConfig &result) {
|
||||
const auto call = weak.get();
|
||||
|
@ -249,14 +316,14 @@ void Instance::refreshDhConfig() {
|
|||
Assert(random.size() == MTP::ModExpFirst::kRandomPowerSize);
|
||||
call->start(random);
|
||||
} else {
|
||||
callFailed(call);
|
||||
_delegate->callFailed(call);
|
||||
}
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
const auto call = weak.get();
|
||||
if (!call) {
|
||||
return;
|
||||
}
|
||||
callFailed(call);
|
||||
_delegate->callFailed(call);
|
||||
}).send();
|
||||
}
|
||||
|
||||
|
@ -277,13 +344,13 @@ bytes::const_span Instance::updateDhConfig(
|
|||
} else if (!validRandom(data.vrandom().v)) {
|
||||
return {};
|
||||
}
|
||||
_dhConfig.g = data.vg().v;
|
||||
_dhConfig.p = std::move(primeBytes);
|
||||
_dhConfig.version = data.vversion().v;
|
||||
_cachedDhConfig->g = data.vg().v;
|
||||
_cachedDhConfig->p = std::move(primeBytes);
|
||||
_cachedDhConfig->version = data.vversion().v;
|
||||
return bytes::make_span(data.vrandom().v);
|
||||
}, [&](const MTPDmessages_dhConfigNotModified &data)
|
||||
-> bytes::const_span {
|
||||
if (!_dhConfig.g || _dhConfig.p.empty()) {
|
||||
if (!_cachedDhConfig->g || _cachedDhConfig->p.empty()) {
|
||||
LOG(("API Error: dhConfigNotModified on zero version."));
|
||||
return {};
|
||||
} 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() {
|
||||
return getVideoCapture();
|
||||
}
|
||||
|
||||
std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::groupCallGetVideoCapture() {
|
||||
return getVideoCapture();
|
||||
}
|
||||
|
||||
std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::getVideoCapture() {
|
||||
std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::getVideoCapture(
|
||||
QString deviceId) {
|
||||
if (deviceId.isEmpty()) {
|
||||
deviceId = Core::App().settings().callVideoInputDeviceId();
|
||||
}
|
||||
if (auto result = _videoCapture.lock()) {
|
||||
result->switchToDevice(deviceId.toStdString());
|
||||
return result;
|
||||
}
|
||||
auto result = std::shared_ptr<tgcalls::VideoCaptureInterface>(
|
||||
tgcalls::VideoCaptureInterface::Create(
|
||||
tgcalls::StaticThreads::getThreads(),
|
||||
Core::App().settings().callVideoInputDeviceId().toStdString()));
|
||||
deviceId.toStdString()));
|
||||
_videoCapture = result;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#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 {
|
||||
enum class PermissionType;
|
||||
|
@ -27,17 +24,22 @@ class Session;
|
|||
namespace Calls::Group {
|
||||
struct JoinInfo;
|
||||
class Panel;
|
||||
class ChooseJoinAsProcess;
|
||||
} // namespace Calls::Group
|
||||
|
||||
namespace tgcalls {
|
||||
class VideoCaptureInterface;
|
||||
} // namespace tgcalls
|
||||
|
||||
namespace Calls {
|
||||
|
||||
class Call;
|
||||
enum class CallType;
|
||||
class GroupCall;
|
||||
class Panel;
|
||||
struct DhConfig;
|
||||
|
||||
class Instance
|
||||
: private Call::Delegate
|
||||
, private GroupCall::Delegate
|
||||
, private base::Subscriber
|
||||
, public base::has_weak_ptr {
|
||||
class Instance : private base::Subscriber, public base::has_weak_ptr {
|
||||
public:
|
||||
Instance();
|
||||
~Instance();
|
||||
|
@ -69,7 +71,8 @@ public:
|
|||
bool activateCurrentCall(const QString &joinHash = QString());
|
||||
bool minimizeCurrentActiveCall();
|
||||
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 setCurrentAudioDevice(bool input, const QString &deviceId);
|
||||
|
@ -77,44 +80,13 @@ public:
|
|||
[[nodiscard]] bool isQuitPrevent();
|
||||
|
||||
private:
|
||||
using CallSound = Call::Delegate::CallSound;
|
||||
using GroupCallSound = GroupCall::Delegate::GroupCallSound;
|
||||
|
||||
[[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;
|
||||
}
|
||||
class Delegate;
|
||||
friend class Delegate;
|
||||
|
||||
not_null<Media::Audio::Track*> ensureSoundLoaded(const QString &key);
|
||||
void playSoundOnce(const QString &key);
|
||||
|
||||
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 {
|
||||
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 createCall(not_null<UserData*> user, CallType type, bool video);
|
||||
void destroyCall(not_null<Call*> call);
|
||||
|
||||
void createGroupCall(
|
||||
|
@ -141,7 +113,8 @@ private:
|
|||
not_null<Main::Session*> session,
|
||||
const MTPUpdate &update);
|
||||
|
||||
DhConfig _dhConfig;
|
||||
const std::unique_ptr<Delegate> _delegate;
|
||||
const std::unique_ptr<DhConfig> _cachedDhConfig;
|
||||
|
||||
crl::time _lastServerConfigUpdateTime = 0;
|
||||
base::weak_ptr<Main::Session> _serverConfigRequestSession;
|
||||
|
@ -157,7 +130,7 @@ private:
|
|||
|
||||
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
|
||||
|
||||
Group::ChooseJoinAsProcess _chooseJoinAs;
|
||||
const std::unique_ptr<Group::ChooseJoinAsProcess> _chooseJoinAs;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "calls/calls_call.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "calls/calls_signal_bars.h"
|
||||
#include "calls/group/calls_group_call.h"
|
||||
#include "calls/group/calls_group_menu.h" // Group::LeaveBox.
|
||||
#include "history/view/history_view_group_call_tracker.h" // ContentByCall.
|
||||
#include "data/data_user.h"
|
||||
|
|
|
@ -313,8 +313,8 @@ GroupCall::GroupCall(
|
|||
, _joinHash(info.joinHash)
|
||||
, _id(inputCall.c_inputGroupCall().vid().v)
|
||||
, _scheduleDate(info.scheduleDate)
|
||||
, _videoOutgoing(std::make_unique<Webrtc::VideoTrack>(
|
||||
Webrtc::VideoState::Inactive))
|
||||
, _videoOutgoing(
|
||||
std::make_unique<Webrtc::VideoTrack>(Webrtc::VideoState::Inactive))
|
||||
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
|
||||
, _checkJoinedTimer([=] { checkJoined(); })
|
||||
, _pushToTalkCancelTimer([=] { pushToTalkCancel(); })
|
||||
|
@ -402,6 +402,7 @@ void GroupCall::switchToCamera() {
|
|||
return;
|
||||
}
|
||||
_videoDeviceId = _videoInputId;
|
||||
if (_videoOutgoing)
|
||||
_videoCapture->switchToDevice(_videoDeviceId.toStdString());
|
||||
}
|
||||
|
||||
|
@ -1366,10 +1367,42 @@ void GroupCall::setupMediaDevices() {
|
|||
}
|
||||
|
||||
void GroupCall::setupOutgoingVideo() {
|
||||
_videoCapture = _delegate->groupCallGetVideoCapture();
|
||||
_videoOutgoing->setState(Webrtc::VideoState::Active);
|
||||
_videoCapture->setOutput(_videoOutgoing->sink());
|
||||
_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) {
|
||||
|
@ -1424,6 +1457,7 @@ void GroupCall::ensureControllerCreated() {
|
|||
|
||||
const auto weak = base::make_weak(this);
|
||||
const auto myLevel = std::make_shared<tgcalls::GroupLevelValue>();
|
||||
_videoCall = true;
|
||||
tgcalls::GroupInstanceDescriptor descriptor = {
|
||||
.threads = tgcalls::StaticThreads::getThreads(),
|
||||
.config = tgcalls::GroupConfig{
|
||||
|
@ -1451,13 +1485,10 @@ void GroupCall::ensureControllerCreated() {
|
|||
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
|
||||
settings.callAudioBackend()),
|
||||
.videoCapture = _videoCapture,
|
||||
//.getVideoSource = [=] {
|
||||
// return _videoCapture->
|
||||
//},
|
||||
.incomingVideoSourcesUpdated = [=](
|
||||
const std::vector<uint32_t> &ssrcs) {
|
||||
crl::on_main(weak, [=] {
|
||||
showVideoStreams(ssrcs);
|
||||
setVideoStreams(ssrcs);
|
||||
});
|
||||
},
|
||||
.participantDescriptionsRequired = [=](
|
||||
|
@ -1609,9 +1640,53 @@ void GroupCall::requestParticipantsInformation(
|
|||
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) {
|
||||
_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();
|
||||
}
|
||||
|
||||
//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 {
|
||||
Expects(_id != 0);
|
||||
|
||||
|
@ -2084,9 +2120,6 @@ MTPInputGroupCall GroupCall::inputCall() const {
|
|||
|
||||
void GroupCall::destroyController() {
|
||||
if (_instance) {
|
||||
//_instance->stop([](tgcalls::FinalState) {
|
||||
//});
|
||||
|
||||
DEBUG_LOG(("Call Info: Destroying call controller.."));
|
||||
_instance.reset();
|
||||
DEBUG_LOG(("Call Info: Call controller destroyed."));
|
||||
|
|
|
@ -74,6 +74,11 @@ struct LevelUpdate {
|
|||
bool me = false;
|
||||
};
|
||||
|
||||
struct StreamsVideoUpdate {
|
||||
uint32 ssrc = 0;
|
||||
bool streams = false;
|
||||
};
|
||||
|
||||
struct VideoParams;
|
||||
|
||||
[[nodiscard]] std::shared_ptr<VideoParams> ParseVideoParams(
|
||||
|
@ -100,7 +105,7 @@ public:
|
|||
Ended,
|
||||
};
|
||||
virtual void groupCallPlaySound(GroupCallSound sound) = 0;
|
||||
virtual auto groupCallGetVideoCapture()
|
||||
virtual auto groupCallGetVideoCapture(const QString &deviceId)
|
||||
-> std::shared_ptr<tgcalls::VideoCaptureInterface> = 0;
|
||||
};
|
||||
|
||||
|
@ -158,6 +163,13 @@ public:
|
|||
return _muted.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool videoCall() const {
|
||||
return _videoCall.current();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<bool> videoCallValue() const {
|
||||
return _videoCall.value();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto otherParticipantStateValue() const
|
||||
-> rpl::producer<Group::ParticipantState>;
|
||||
|
||||
|
@ -194,8 +206,15 @@ public:
|
|||
[[nodiscard]] rpl::producer<LevelUpdate> levelUpdates() const {
|
||||
return _levelUpdates.events();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<uint32> videoStreamUpdated() const {
|
||||
return _videoStreamUpdated.events();
|
||||
[[nodiscard]] auto streamsVideoUpdates() const
|
||||
-> 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 {
|
||||
return _rejoinEvents.events();
|
||||
|
@ -213,8 +232,6 @@ public:
|
|||
bool isScreenSharing() const;
|
||||
void switchToCamera();
|
||||
void switchToScreenSharing(const QString &uniqueId);
|
||||
//void setAudioVolume(bool input, float level);
|
||||
void setAudioDuckingEnabled(bool enabled);
|
||||
|
||||
void toggleMute(const Group::MuteRequest &data);
|
||||
void changeVolume(const Group::VolumeRequest &data);
|
||||
|
@ -264,8 +281,6 @@ private:
|
|||
void handlePossibleDiscarded(const MTPDgroupCallDiscarded &data);
|
||||
void handleUpdate(const MTPDupdateGroupCall &data);
|
||||
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
|
||||
void handleRequestError(const MTP::Error &error);
|
||||
void handleControllerError(const QString &error);
|
||||
void ensureControllerCreated();
|
||||
void destroyController();
|
||||
|
||||
|
@ -304,7 +319,7 @@ private:
|
|||
const Data::GroupCallParticipant &participant);
|
||||
void addPreparedParticipants();
|
||||
void addPreparedParticipantsDelayed();
|
||||
void showVideoStreams(const std::vector<std::uint32_t> &ssrcs);
|
||||
void setVideoStreams(const std::vector<std::uint32_t> &ssrcs);
|
||||
|
||||
void editParticipant(
|
||||
not_null<PeerData*> participantPeer,
|
||||
|
@ -347,6 +362,7 @@ private:
|
|||
QString _joinHash;
|
||||
|
||||
rpl::variable<MuteState> _muted = MuteState::Muted;
|
||||
rpl::variable<bool> _videoCall = false;
|
||||
bool _initialMuteStateSent = false;
|
||||
bool _acceptFields = false;
|
||||
|
||||
|
@ -365,7 +381,10 @@ private:
|
|||
std::shared_ptr<tgcalls::VideoCaptureInterface> _videoCapture;
|
||||
const std::unique_ptr<Webrtc::VideoTrack> _videoOutgoing;
|
||||
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;
|
||||
rpl::event_stream<Group::RejoinEvent> _rejoinEvents;
|
||||
rpl::event_stream<> _allowedToSpeakNotifications;
|
||||
|
|
|
@ -47,4 +47,9 @@ struct JoinInfo {
|
|||
TimeId scheduleDate = 0;
|
||||
};
|
||||
|
||||
enum class PanelMode {
|
||||
Default,
|
||||
Wide,
|
||||
};
|
||||
|
||||
} // namespace Calls::Group
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
}
|
||||
|
||||
[[nodiscard]] not_null<Webrtc::VideoTrack*> createVideoTrack();
|
||||
void clearVideoTrack();
|
||||
void setVideoTrack(not_null<Webrtc::VideoTrack*> track);
|
||||
|
||||
void addActionRipple(QPoint point, Fn<void()> updateCallback) override;
|
||||
|
@ -352,12 +353,14 @@ private:
|
|||
not_null<Row*> row,
|
||||
uint64 raiseHandRating) const;
|
||||
Row *findRow(not_null<PeerData*> participantPeer) const;
|
||||
Row *findRow(uint32 audioSsrc) const;
|
||||
|
||||
void appendInvitedUsers();
|
||||
void scheduleRaisedHandStatusRemove();
|
||||
|
||||
const not_null<GroupCall*> _call;
|
||||
not_null<PeerData*> _peer;
|
||||
uint32 _largeSsrc = 0;
|
||||
bool _prepared = false;
|
||||
|
||||
rpl::event_stream<MuteRequest> _toggleMuteRequests;
|
||||
|
@ -926,6 +929,13 @@ not_null<Webrtc::VideoTrack*> Row::createVideoTrack() {
|
|||
return _videoTrack.get();
|
||||
}
|
||||
|
||||
void Row::clearVideoTrack() {
|
||||
_videoTrackLifetime.destroy();
|
||||
_videoTrackShown = nullptr;
|
||||
_videoTrack = nullptr;
|
||||
_delegate->rowUpdateRow(this);
|
||||
}
|
||||
|
||||
void Row::setVideoTrack(not_null<Webrtc::VideoTrack*> track) {
|
||||
_videoTrackLifetime.destroy();
|
||||
_videoTrackShown = track;
|
||||
|
@ -1043,17 +1053,29 @@ void MembersController::setupListChangeViewers() {
|
|||
}
|
||||
}, _lifetime);
|
||||
|
||||
_call->videoStreamUpdated(
|
||||
) | rpl::start_with_next([=](uint32 ssrc) {
|
||||
const auto real = _call->lookupReal();
|
||||
const auto participantPeer = real
|
||||
? real->participantPeerByAudioSsrc(ssrc)
|
||||
: nullptr;
|
||||
const auto row = participantPeer
|
||||
? findRow(participantPeer)
|
||||
: nullptr;
|
||||
if (row) {
|
||||
_call->addVideoOutput(ssrc, row->createVideoTrack());
|
||||
|
||||
_call->videoStreamLargeValue(
|
||||
) | rpl::filter([=](uint32 largeSsrc) {
|
||||
return (_largeSsrc != largeSsrc);
|
||||
}) | rpl::start_with_next([=](uint32 largeSsrc) {
|
||||
if (const auto row = findRow(_largeSsrc)) {
|
||||
_call->addVideoOutput(_largeSsrc, row->createVideoTrack());
|
||||
}
|
||||
_largeSsrc = largeSsrc;
|
||||
if (const auto row = findRow(_largeSsrc)) {
|
||||
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);
|
||||
|
||||
|
@ -1345,8 +1367,6 @@ void MembersController::updateRow(
|
|||
}
|
||||
if (isMe(row->peer())) {
|
||||
row->setVideoTrack(_call->outgoingVideoTrack());
|
||||
} else if (nowSsrc) {
|
||||
_call->addVideoOutput(nowSsrc, row->createVideoTrack());
|
||||
}
|
||||
}
|
||||
const auto nowNoSounding = _soundingRowBySsrc.empty();
|
||||
|
@ -1378,6 +1398,17 @@ Row *MembersController::findRow(not_null<PeerData*> participantPeer) const {
|
|||
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 {
|
||||
return _call->peer()->session();
|
||||
}
|
||||
|
@ -1943,8 +1974,11 @@ int Members::desiredHeight() const {
|
|||
return 0;
|
||||
}();
|
||||
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
|
||||
+ (use * st::groupCallMembersList.item.height)
|
||||
+ (use * single)
|
||||
+ (use ? st::lineWidth : 0);
|
||||
}
|
||||
|
||||
|
@ -2008,6 +2042,16 @@ void Members::setupAddMember(not_null<GroupCall*> call) {
|
|||
}, 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 {
|
||||
return static_cast<MembersController*>(
|
||||
_listController.get())->fullCountValue();
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Calls::Group {
|
|||
|
||||
struct VolumeRequest;
|
||||
struct MuteRequest;
|
||||
enum class PanelMode;
|
||||
|
||||
class Members final
|
||||
: public Ui::RpWidget
|
||||
|
@ -48,6 +49,8 @@ public:
|
|||
return _addMemberRequests.events();
|
||||
}
|
||||
|
||||
void setMode(PanelMode mode);
|
||||
|
||||
private:
|
||||
using ListWidget = PeerListContent;
|
||||
|
||||
|
@ -76,6 +79,7 @@ private:
|
|||
void updateControlsGeometry();
|
||||
|
||||
const not_null<GroupCall*> _call;
|
||||
PanelMode _mode = PanelMode();
|
||||
object_ptr<Ui::ScrollArea> _scroll;
|
||||
std::unique_ptr<PeerListController> _listController;
|
||||
object_ptr<Ui::SettingsButton> _addMember = { nullptr };
|
||||
|
|
|
@ -525,6 +525,11 @@ void Panel::initWindow() {
|
|||
? (Flag::Move | Flag::Maximize)
|
||||
: Flag::None;
|
||||
});
|
||||
|
||||
_call->videoCallValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateMode();
|
||||
}, _window->lifetime());
|
||||
}
|
||||
|
||||
void Panel::initWidget() {
|
||||
|
@ -536,8 +541,10 @@ void Panel::initWidget() {
|
|||
}, widget()->lifetime());
|
||||
|
||||
widget()->sizeValue(
|
||||
) | rpl::skip(1) | rpl::start_with_next([=] {
|
||||
updateControlsGeometry();
|
||||
) | rpl::skip(1) | rpl::start_with_next([=](QSize size) {
|
||||
if (!updateMode()) {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
// title geometry depends on _controls->geometry,
|
||||
// which is not updated here yet.
|
||||
|
@ -1384,6 +1391,21 @@ QRect Panel::computeTitleRect() const {
|
|||
#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() {
|
||||
if (widget()->size().isEmpty() || (!_settings && !_share)) {
|
||||
return;
|
||||
|
@ -1434,27 +1456,35 @@ void Panel::updateMembersGeometry() {
|
|||
if (!_members) {
|
||||
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 membersWidthAvailable = widget()->width()
|
||||
- st::groupCallMembersMargin.left()
|
||||
- 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));
|
||||
if (_mode == PanelMode::Wide) {
|
||||
_members->setGeometry(
|
||||
st::groupCallNarrowSkip,
|
||||
0,
|
||||
st::groupCallNarrowSize.width(),
|
||||
std::min(desiredHeight, widget()->height()));
|
||||
} else {
|
||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
||||
const auto membersTop = st::groupCallMembersTop;
|
||||
const auto availableHeight = muteTop
|
||||
- membersTop
|
||||
- st::groupCallMembersMargin.bottom();
|
||||
const auto membersWidthAvailable = widget()->width()
|
||||
- st::groupCallMembersMargin.left()
|
||||
- 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() {
|
||||
|
|
|
@ -53,6 +53,7 @@ struct CallBodyLayout;
|
|||
namespace Calls::Group {
|
||||
|
||||
class Members;
|
||||
enum class PanelMode;
|
||||
|
||||
class Panel final : private Ui::DesktopCapture::ChooseSourceDelegate {
|
||||
public:
|
||||
|
@ -88,6 +89,7 @@ private:
|
|||
bool handleClose();
|
||||
void startScheduledNow();
|
||||
|
||||
bool updateMode();
|
||||
void updateControlsGeometry();
|
||||
void updateMembersGeometry();
|
||||
void showControls();
|
||||
|
@ -118,6 +120,7 @@ private:
|
|||
|
||||
const std::unique_ptr<Ui::Window> _window;
|
||||
const std::unique_ptr<Ui::LayerManager> _layerBg;
|
||||
PanelMode _mode = PanelMode();
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
std::unique_ptr<Ui::Platform::TitleControls> _controls;
|
||||
|
|
|
@ -93,8 +93,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "core/application.h"
|
||||
#include "core/changelogs.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "calls/calls_call.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "calls/calls_top_bar.h"
|
||||
#include "calls/group/calls_group_call.h"
|
||||
#include "export/export_settings.h"
|
||||
#include "export/export_manager.h"
|
||||
#include "export/view/export_view_top_bar.h"
|
||||
|
|
|
@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/window_session_controller.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "calls/calls_call.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "calls/calls_video_bubble.h"
|
||||
#include "webrtc/webrtc_media_devices.h"
|
||||
|
@ -250,40 +251,6 @@ void Calls::setupContent() {
|
|||
AddSkip(content);
|
||||
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(
|
||||
content,
|
||||
tr::lng_settings_call_accept_calls(),
|
||||
|
|
|
@ -42,6 +42,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/toast/toast.h"
|
||||
#include "ui/toasts/common_toasts.h"
|
||||
#include "calls/calls_instance.h" // Core::App().calls().inCall().
|
||||
#include "calls/group/calls_group_call.h"
|
||||
#include "ui/boxes/calendar_box.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "mainwidget.h"
|
||||
|
|
Loading…
Add table
Reference in a new issue