Allow sharing screen with sound on Windows.

This commit is contained in:
John Preston 2021-07-13 16:27:44 +03:00
parent 402729dc99
commit db81638656
13 changed files with 129 additions and 27 deletions

View File

@ -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";

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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;
};

@ -1 +1 @@
Subproject commit 3cf1822a70e3b84f6a762755e5249b26e915d321
Subproject commit 07e0484a583121870316f3039aa2047ed030cd6d

View File

@ -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

View File

@ -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" ^

View File

@ -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" ^