mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Allow sharing screen with sound on Windows.
This commit is contained in:
parent
402729dc99
commit
db81638656
13 changed files with 129 additions and 27 deletions
|
@ -2021,6 +2021,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_group_call_screen_share_start" = "Share Screen";
|
||||
"lng_group_call_screen_share_stop" = "Stop Sharing";
|
||||
"lng_group_call_screen_title" = "Screen {index}";
|
||||
"lng_group_call_screen_share_audio" = "Share Audio";
|
||||
"lng_group_call_unmute_small" = "Unmute";
|
||||
"lng_group_call_more" = "More";
|
||||
"lng_group_call_unmute" = "Unmute";
|
||||
|
|
|
@ -1184,6 +1184,16 @@ desktopCaptureSubmit: RoundButton(desktopCaptureCancel) {
|
|||
color: shadowFg;
|
||||
}
|
||||
}
|
||||
desktopCaptureWithAudio: Checkbox(defaultCheckbox) {
|
||||
textFg: groupCallMembersFg;
|
||||
textFgActive: groupCallMembersFg;
|
||||
rippleBg: groupCallMembersBgRipple;
|
||||
rippleBgActive: groupCallMembersBgRipple;
|
||||
style: semiboldTextStyle;
|
||||
}
|
||||
desktopCaptureWithAudioCheck: Check(defaultCheck) {
|
||||
untoggledFg: groupCallActiveFg;
|
||||
}
|
||||
|
||||
groupCallNarrowSkip: 9px;
|
||||
groupCallNarrowMembersWidth: 204px;
|
||||
|
|
|
@ -613,6 +613,10 @@ QString GroupCall::screenSharingDeviceId() const {
|
|||
return isSharingScreen() ? _screenDeviceId : QString();
|
||||
}
|
||||
|
||||
bool GroupCall::screenSharingWithAudio() const {
|
||||
return isSharingScreen() && _screenWithAudio;
|
||||
}
|
||||
|
||||
bool GroupCall::mutedByAdmin() const {
|
||||
const auto mute = muted();
|
||||
return mute == MuteState::ForceMuted || mute == MuteState::RaisedHand;
|
||||
|
@ -635,7 +639,9 @@ void GroupCall::toggleVideo(bool active) {
|
|||
: Webrtc::VideoState::Inactive;
|
||||
}
|
||||
|
||||
void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
|
||||
void GroupCall::toggleScreenSharing(
|
||||
std::optional<QString> uniqueId,
|
||||
bool withAudio) {
|
||||
if (!_instance || !_id) {
|
||||
return;
|
||||
} else if (!uniqueId) {
|
||||
|
@ -645,10 +651,14 @@ void GroupCall::toggleScreenSharing(std::optional<QString> uniqueId) {
|
|||
const auto changed = (_screenDeviceId != *uniqueId);
|
||||
const auto wasSharing = isSharingScreen();
|
||||
_screenDeviceId = *uniqueId;
|
||||
_screenWithAudio = withAudio;
|
||||
_screenState = Webrtc::VideoState::Active;
|
||||
if (changed && wasSharing && isSharingScreen()) {
|
||||
_screenCapture->switchToDevice(uniqueId->toStdString());
|
||||
}
|
||||
if (_screenInstance) {
|
||||
_screenInstance->setIsMuted(!withAudio);
|
||||
}
|
||||
}
|
||||
|
||||
bool GroupCall::hasVideoWithFrames() const {
|
||||
|
@ -2281,9 +2291,7 @@ bool GroupCall::tryCreateScreencast() {
|
|||
_screenInstance = std::make_unique<tgcalls::GroupInstanceCustomImpl>(
|
||||
std::move(descriptor));
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
_screenInstance->setIsMuted(false);
|
||||
#endif // Q_OS_WIN
|
||||
_screenInstance->setIsMuted(!_screenWithAudio);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -380,8 +380,11 @@ public:
|
|||
[[nodiscard]] bool isCameraPaused() const;
|
||||
[[nodiscard]] const std::string &cameraSharingEndpoint() const;
|
||||
[[nodiscard]] QString screenSharingDeviceId() const;
|
||||
[[nodiscard]] bool screenSharingWithAudio() const;
|
||||
void toggleVideo(bool active);
|
||||
void toggleScreenSharing(std::optional<QString> uniqueId);
|
||||
void toggleScreenSharing(
|
||||
std::optional<QString> uniqueId,
|
||||
bool withAudio = false);
|
||||
[[nodiscard]] bool hasVideoWithFrames() const;
|
||||
[[nodiscard]] rpl::producer<bool> hasVideoWithFramesValue() const;
|
||||
|
||||
|
@ -614,6 +617,7 @@ private:
|
|||
rpl::variable<Webrtc::VideoState> _screenState;
|
||||
rpl::variable<bool> _isSharingScreen = false;
|
||||
QString _screenDeviceId;
|
||||
bool _screenWithAudio = false;
|
||||
|
||||
base::flags<SendUpdateType> _pendingSelfUpdates;
|
||||
bool _requireARGB32 = true;
|
||||
|
|
|
@ -260,12 +260,26 @@ QString Panel::chooseSourceActiveDeviceId() {
|
|||
return _call->screenSharingDeviceId();
|
||||
}
|
||||
|
||||
bool Panel::chooseSourceActiveWithAudio() {
|
||||
return _call->screenSharingWithAudio();
|
||||
}
|
||||
|
||||
bool Panel::chooseSourceWithAudioSupported() {
|
||||
#ifdef Q_OS_WIN
|
||||
return true;
|
||||
#else // Q_OS_WIN
|
||||
return false;
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
rpl::lifetime &Panel::chooseSourceInstanceLifetime() {
|
||||
return lifetime();
|
||||
}
|
||||
|
||||
void Panel::chooseSourceAccepted(const QString &deviceId) {
|
||||
_call->toggleScreenSharing(deviceId);
|
||||
void Panel::chooseSourceAccepted(
|
||||
const QString &deviceId,
|
||||
bool withAudio) {
|
||||
_call->toggleScreenSharing(deviceId, withAudio);
|
||||
}
|
||||
|
||||
void Panel::chooseSourceStop() {
|
||||
|
@ -1185,7 +1199,7 @@ void Panel::chooseShareScreenSource() {
|
|||
if (_call->isSharingScreen()) {
|
||||
_call->toggleScreenSharing(std::nullopt);
|
||||
} else {
|
||||
chooseSourceAccepted(*source);
|
||||
chooseSourceAccepted(*source, false);
|
||||
}
|
||||
} else {
|
||||
Ui::DesktopCapture::ChooseSource(this);
|
||||
|
|
|
@ -169,8 +169,12 @@ private:
|
|||
|
||||
QWidget *chooseSourceParent() override;
|
||||
QString chooseSourceActiveDeviceId() override;
|
||||
bool chooseSourceActiveWithAudio() override;
|
||||
bool chooseSourceWithAudioSupported() override;
|
||||
rpl::lifetime &chooseSourceInstanceLifetime() override;
|
||||
void chooseSourceAccepted(const QString &deviceId) override;
|
||||
void chooseSourceAccepted(
|
||||
const QString &deviceId,
|
||||
bool withAudio) override;
|
||||
void chooseSourceStop() override;
|
||||
|
||||
const not_null<GroupCall*> _call;
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/image/image.h"
|
||||
#include "ui/platform/ui_platform_window_title.h"
|
||||
|
@ -62,6 +63,8 @@ public:
|
|||
|
||||
[[nodiscard]] rpl::producer<> activations() const;
|
||||
void setActive(bool active);
|
||||
[[nodiscard]] bool isWindow() const;
|
||||
[[nodiscard]] QString deviceIdKey() const;
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
|
@ -94,6 +97,7 @@ private:
|
|||
void setupGeometryWithParent(not_null<QWidget*> parent);
|
||||
void fillSources();
|
||||
void setupSourcesGeometry();
|
||||
void updateButtonsVisibility();
|
||||
void destroy();
|
||||
|
||||
static base::flat_map<
|
||||
|
@ -107,6 +111,7 @@ private:
|
|||
const not_null<RpWidget*> _bottom;
|
||||
const not_null<RoundButton*> _submit;
|
||||
const not_null<RoundButton*> _finish;
|
||||
const not_null<Checkbox*> _withAudio;
|
||||
|
||||
std::vector<std::unique_ptr<Source>> _sources;
|
||||
Source *_selected = nullptr;
|
||||
|
@ -166,6 +171,14 @@ rpl::producer<> Source::activations() const {
|
|||
return _activations.events();
|
||||
}
|
||||
|
||||
bool Source::isWindow() const {
|
||||
return _source.isWindow();
|
||||
}
|
||||
|
||||
QString Source::deviceIdKey() const {
|
||||
return QString::fromStdString(_source.deviceIdKey());
|
||||
}
|
||||
|
||||
void Source::setActive(bool active) {
|
||||
if (_active != active) {
|
||||
_active = active;
|
||||
|
@ -255,7 +268,13 @@ ChooseSourceProcess::ChooseSourceProcess(
|
|||
CreateChild<RoundButton>(
|
||||
_bottom.get(),
|
||||
tr::lng_group_call_screen_share_stop(),
|
||||
st::desktopCaptureFinish)) {
|
||||
st::desktopCaptureFinish))
|
||||
, _withAudio(
|
||||
CreateChild<Checkbox>(
|
||||
_bottom.get(),
|
||||
tr::lng_group_call_screen_share_audio(tr::now),
|
||||
false,
|
||||
st::desktopCaptureWithAudio)) {
|
||||
setupPanel();
|
||||
setupSources();
|
||||
activate();
|
||||
|
@ -336,7 +355,9 @@ void ChooseSourceProcess::setupPanel() {
|
|||
return;
|
||||
}
|
||||
const auto weak = MakeWeak(_window.get());
|
||||
_delegate->chooseSourceAccepted(_selectedId);
|
||||
_delegate->chooseSourceAccepted(
|
||||
_selectedId,
|
||||
!_withAudio->isHidden() && _withAudio->checked());
|
||||
if (const auto strong = weak.data()) {
|
||||
strong->close();
|
||||
}
|
||||
|
@ -375,6 +396,18 @@ void ChooseSourceProcess::setupPanel() {
|
|||
bottomSkip);
|
||||
}, _bottom->lifetime());
|
||||
|
||||
_withAudio->widthValue(
|
||||
) | rpl::start_with_next([=](int width) {
|
||||
const auto top = (bottomHeight - _withAudio->heightNoMargins()) / 2;
|
||||
_withAudio->moveToLeft(bottomSkip, top);
|
||||
}, _withAudio->lifetime());
|
||||
|
||||
_withAudio->setChecked(_delegate->chooseSourceActiveWithAudio());
|
||||
_withAudio->checkedChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateButtonsVisibility();
|
||||
}, _withAudio->lifetime());
|
||||
|
||||
const auto sharing = !_delegate->chooseSourceActiveDeviceId().isEmpty();
|
||||
_finish->setVisible(sharing);
|
||||
_submit->setVisible(!sharing);
|
||||
|
@ -420,6 +453,8 @@ void ChooseSourceProcess::fillSources() {
|
|||
auto screensManager = tgcalls::DesktopCaptureSourceManager(Type::Screen);
|
||||
auto windowsManager = tgcalls::DesktopCaptureSourceManager(Type::Window);
|
||||
|
||||
_withAudio->setVisible(false);
|
||||
|
||||
auto screenIndex = 0;
|
||||
auto windowIndex = 0;
|
||||
const auto active = _delegate->chooseSourceActiveDeviceId();
|
||||
|
@ -435,9 +470,13 @@ void ChooseSourceProcess::fillSources() {
|
|||
const auto id = source.deviceIdKey();
|
||||
_sources.push_back(std::make_unique<Source>(_inner, source, title));
|
||||
|
||||
const auto withAudioSupported = !source.isWindow()
|
||||
&& _delegate->chooseSourceWithAudioSupported();
|
||||
|
||||
const auto raw = _sources.back().get();
|
||||
if (!active.isEmpty() && active.toStdString() == id) {
|
||||
_selected = raw;
|
||||
_withAudio->setVisible(withAudioSupported);
|
||||
raw->setActive(true);
|
||||
}
|
||||
_sources.back()->activations(
|
||||
|
@ -448,15 +487,8 @@ void ChooseSourceProcess::fillSources() {
|
|||
_selected->setActive(false);
|
||||
}
|
||||
_selected = raw;
|
||||
_selectedId = QString::fromStdString(id);
|
||||
if (_selectedId == _delegate->chooseSourceActiveDeviceId()) {
|
||||
_selectedId = QString();
|
||||
_finish->setVisible(true);
|
||||
_submit->setVisible(false);
|
||||
} else {
|
||||
_finish->setVisible(false);
|
||||
_submit->setVisible(true);
|
||||
}
|
||||
_withAudio->setVisible(withAudioSupported);
|
||||
updateButtonsVisibility();
|
||||
}, raw->lifetime());
|
||||
};
|
||||
for (const auto &source : screensManager.sources()) {
|
||||
|
@ -467,6 +499,27 @@ void ChooseSourceProcess::fillSources() {
|
|||
}
|
||||
}
|
||||
|
||||
void ChooseSourceProcess::updateButtonsVisibility() {
|
||||
const auto withAudioSupported = _selected
|
||||
&& !_selected->isWindow()
|
||||
&& _delegate->chooseSourceWithAudioSupported();
|
||||
const auto selectedId = _selected
|
||||
? _selected->deviceIdKey()
|
||||
: QString();
|
||||
if (selectedId == _delegate->chooseSourceActiveDeviceId()
|
||||
&& (!withAudioSupported
|
||||
|| (_withAudio->checked()
|
||||
== _delegate->chooseSourceActiveWithAudio()))) {
|
||||
_selectedId = QString();
|
||||
_finish->setVisible(true);
|
||||
_submit->setVisible(false);
|
||||
} else {
|
||||
_selectedId = selectedId;
|
||||
_finish->setVisible(false);
|
||||
_submit->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ChooseSourceProcess::setupSourcesGeometry() {
|
||||
if (_sources.empty()) {
|
||||
destroy();
|
||||
|
|
|
@ -20,8 +20,12 @@ class ChooseSourceDelegate {
|
|||
public:
|
||||
virtual QWidget *chooseSourceParent() = 0;
|
||||
virtual QString chooseSourceActiveDeviceId() = 0;
|
||||
virtual bool chooseSourceActiveWithAudio() = 0;
|
||||
virtual bool chooseSourceWithAudioSupported() = 0;
|
||||
virtual rpl::lifetime &chooseSourceInstanceLifetime() = 0;
|
||||
virtual void chooseSourceAccepted(const QString &deviceId) = 0;
|
||||
virtual void chooseSourceAccepted(
|
||||
const QString &deviceId,
|
||||
bool withAudio) = 0;
|
||||
virtual void chooseSourceStop() = 0;
|
||||
};
|
||||
|
||||
|
|
2
Telegram/ThirdParty/tgcalls
vendored
2
Telegram/ThirdParty/tgcalls
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 3cf1822a70e3b84f6a762755e5249b26e915d321
|
||||
Subproject commit 07e0484a583121870316f3039aa2047ed030cd6d
|
|
@ -49,9 +49,13 @@ PRIVATE
|
|||
Message.h
|
||||
NetworkManager.cpp
|
||||
NetworkManager.h
|
||||
SctpDataChannelProviderInterfaceImpl.cpp
|
||||
SctpDataChannelProviderInterfaceImpl.h
|
||||
StaticThreads.cpp
|
||||
StaticThreads.h
|
||||
ThreadLocalObject.h
|
||||
TurnCustomizerImpl.cpp
|
||||
TurnCustomizerImpl.h
|
||||
VideoCaptureInterface.cpp
|
||||
VideoCaptureInterface.h
|
||||
VideoCaptureInterfaceImpl.cpp
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 5d16a97b57f0399d552e0c9dd72d27e81f6a8316
|
||||
Subproject commit 3bd9b94e928b2ce963290d773926240ec2612d6a
|
|
@ -110,9 +110,9 @@ Open **x64 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
|
|||
cmake --build . --config Release
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/kcat/openal-soft.git
|
||||
git clone https://github.com/telegramdesktop/openal-soft.git
|
||||
cd openal-soft
|
||||
git checkout openal-soft-1.21.0
|
||||
git checkout wasapi_exact_device_time
|
||||
cd build
|
||||
cmake .. ^
|
||||
-G "Visual Studio 16 2019" ^
|
||||
|
|
|
@ -110,9 +110,9 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
|
|||
cmake --build . --config Release
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/kcat/openal-soft.git
|
||||
git clone https://github.com/telegramdesktop/openal-soft.git
|
||||
cd openal-soft
|
||||
git checkout openal-soft-1.21.0
|
||||
git checkout wasapi_exact_device_time
|
||||
cd build
|
||||
cmake .. ^
|
||||
-G "Visual Studio 16 2019" ^
|
||||
|
|
Loading…
Add table
Reference in a new issue