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