diff --git a/.gitmodules b/.gitmodules index e0dcccaa9a..48fe67ce6c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,3 +97,6 @@ [submodule "Telegram/lib_webrtc"] path = Telegram/lib_webrtc url = https://github.com/desktop-app/lib_webrtc.git +[submodule "Telegram/ThirdParty/tgcalls"] + path = Telegram/ThirdParty/tgcalls + url = https://github.com/TelegramMessenger/tgcalls.git diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index b2fd96b26d..14b902a462 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -35,6 +35,7 @@ include(cmake/lib_ffmpeg.cmake) include(cmake/lib_mtproto.cmake) include(cmake/lib_scheme.cmake) include(cmake/lib_tgvoip.cmake) +include(cmake/lib_tgcalls.cmake) set(style_files boxes/boxes.style @@ -102,6 +103,8 @@ endif() target_link_libraries(Telegram PRIVATE + tdesktop::lib_tgcalls_legacy + tdesktop::lib_tgcalls tdesktop::lib_tgvoip tdesktop::lib_mtproto tdesktop::lib_scheme @@ -315,11 +318,6 @@ PRIVATE calls/calls_box_controller.h calls/calls_call.cpp calls/calls_call.h - calls/calls_controller.cpp - calls/calls_controller.h - calls/calls_controller_tgvoip.h - calls/calls_controller_webrtc.cpp - calls/calls_controller_webrtc.h calls/calls_emoji_fingerprint.cpp calls/calls_emoji_fingerprint.h calls/calls_instance.cpp diff --git a/Telegram/SourceFiles/calls/calls_call.cpp b/Telegram/SourceFiles/calls/calls_call.cpp index 81e285735a..7746ab533d 100644 --- a/Telegram/SourceFiles/calls/calls_call.cpp +++ b/Telegram/SourceFiles/calls/calls_call.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_call.h" #include "main/main_session.h" +#include "main/main_account.h" +#include "main/main_app_config.h" #include "apiwrap.h" #include "lang/lang_keys.h" #include "boxes/confirm_box.h" @@ -21,11 +23,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "media/audio/media_audio_track.h" #include "base/platform/base_platform_info.h" #include "calls/calls_panel.h" -#include "calls/calls_controller.h" #include "data/data_user.h" #include "data/data_session.h" #include "facades.h" +#include "tgcalls/Instance.h" + +namespace tgcalls { +class InstanceImpl; +class InstanceImplLegacy; +void SetLegacyGlobalServerConfig(const std::string &serverConfig); +} // namespace tgcalls + namespace Calls { namespace { @@ -34,20 +43,23 @@ constexpr auto kHangupTimeoutMs = 5000; constexpr auto kSha256Size = 32; const auto kDefaultVersion = "2.4.4"_q; +const auto RegisterTag = tgcalls::Register(); +const auto RegisterTagLegacy = tgcalls::Register(); + void AppendEndpoint( - std::vector &list, + std::vector &list, const MTPPhoneConnection &connection) { connection.match([&](const MTPDphoneConnection &data) { if (data.vpeer_tag().v.length() != 16) { return; } - auto endpoint = TgVoipEndpoint{ + auto endpoint = tgcalls::Endpoint{ .endpointId = (int64_t)data.vid().v, - .host = TgVoipEdpointHost{ + .host = tgcalls::EndpointHost{ .ipv4 = data.vip().v.toStdString(), .ipv6 = data.vipv6().v.toStdString() }, .port = (uint16_t)data.vport().v, - .type = TgVoipEndpointType::UdpRelay + .type = tgcalls::EndpointType::UdpRelay }; const auto tag = data.vpeer_tag().v; if (tag.size() >= 16) { @@ -83,7 +95,48 @@ uint64 ComputeFingerprint(bytes::const_span authKey) { } [[nodiscard]] QVector CollectVersionsForApi() { - return WrapVersions(CollectControllerVersions()); + return WrapVersions(tgcalls::Meta::Versions() | ranges::action::reverse); +} + +[[nodiscard]] std::vector CollectRtcServers( + not_null user) { + using tgcalls::RtcServer; + using List = std::vector>; + + auto result = std::vector(); + const auto list = user->account().appConfig().get( + "rtc_servers", + List()); + result.reserve(list.size() * 2); + for (const auto &entry : list) { + const auto find = [&](const QString &key) { + const auto i = entry.find(key); + return (i != entry.end()) ? i->second : QString(); + }; + const auto host = find(u"host"_q).toStdString(); + const auto port = find(u"port"_q).toUShort(); + const auto username = find(u"username"_q).toStdString(); + const auto password = find(u"password"_q).toStdString(); + if (host.empty() || !port) { + continue; + } + result.push_back(RtcServer{ + .host = host, + .port = port, + .isTurn = false + }); + if (username.empty() || password.empty()) { + continue; + } + result.push_back(RtcServer{ + .host = host, + .port = port, + .login = username, + .password = password, + .isTurn = true, + }); + } + return result; } } // namespace @@ -165,7 +218,7 @@ void Call::startOutgoing() { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(ControllerMaxLayer()), + MTP_int(tgcalls::Meta::MaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -246,7 +299,7 @@ void Call::actuallyAnswer() { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(ControllerMaxLayer()), + MTP_int(tgcalls::Meta::MaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -267,8 +320,8 @@ void Call::actuallyAnswer() { void Call::setMute(bool mute) { _mute = mute; - if (_controller) { - _controller->setMuteMicrophone(_mute); + if (_instance) { + _instance->setMuteMicrophone(_mute); } _muteChanged.notify(_mute); } @@ -294,7 +347,7 @@ void Call::redial() { if (_state.current() != State::Busy) { return; } - Assert(_controller == nullptr); + Assert(_instance == nullptr); _type = Type::Outgoing; setState(State::Requesting); _answerAfterDhConfigReceived = false; @@ -303,7 +356,7 @@ void Call::redial() { } QString Call::getDebugLog() const { - return QString::fromStdString(_controller->getDebugInfo()); + return QString::fromStdString(_instance->getDebugInfo()); } void Call::startWaitingTrack() { @@ -418,7 +471,7 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { } if (_type == Type::Incoming && _state.current() == State::ExchangingKeys - && !_controller) { + && !_instance) { startConfirmedCall(data); } } return true; @@ -429,8 +482,8 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { return false; } if (data.is_need_debug()) { - auto debugLog = _controller - ? _controller->getDebugInfo() + auto debugLog = _instance + ? _instance->getDebugInfo() : std::string(); if (!debugLog.empty()) { user()->session().api().request(MTPphone_SaveCallDebug( @@ -478,17 +531,23 @@ bool Call::handleUpdate(const MTPPhoneCall &call) { bool Call::handleSignalingData( const MTPDupdatePhoneCallSignalingData &data) { - if (data.vphone_call_id().v != _id || !_controller) { + if (data.vphone_call_id().v != _id || !_instance) { return false; } - return _controller->receiveSignalingData(data.vdata().v); + auto prepared = ranges::view::all( + data.vdata().v + ) | ranges::view::transform([](char byte) { + return static_cast(byte); + }) | ranges::to_vector; + _instance->receiveSignalingData(std::move(prepared)); + return true; } void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { Expects(_type == Type::Outgoing); if (_state.current() == State::ExchangingKeys - || _controller) { + || _instance) { LOG(("Call Warning: Unexpected confirmAcceptedCall.")); return; } @@ -516,7 +575,7 @@ void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) { MTP_flags(MTPDphoneCallProtocol::Flag::f_udp_p2p | MTPDphoneCallProtocol::Flag::f_udp_reflector), MTP_int(kMinLayer), - MTP_int(ControllerMaxLayer()), + MTP_int(tgcalls::Meta::MaxLayer()), MTP_vector(CollectVersionsForApi())) )).done([=](const MTPphone_PhoneCall &result) { Expects(result.type() == mtpc_phone_phoneCall); @@ -568,52 +627,80 @@ void Call::createAndStartController(const MTPDphoneCall &call) { const auto &protocol = call.vprotocol().c_phoneCallProtocol(); const auto &serverConfig = _user->session().serverConfig(); - TgVoipConfig config; - config.dataSaving = TgVoipDataSaving::Never; - config.enableAEC = !Platform::IsMac10_7OrGreater(); - config.enableNS = true; - config.enableAGC = true; - config.enableVolumeControl = true; - config.initializationTimeout = serverConfig.callConnectTimeoutMs / 1000.; - config.receiveTimeout = serverConfig.callPacketTimeoutMs / 1000.; - config.enableP2P = call.is_p2p_allowed(); - config.maxApiLayer = protocol.vmax_layer().v; + const auto weak = base::make_weak(this); + auto descriptor = tgcalls::Descriptor{ + .config = tgcalls::Config{ + .initializationTimeout = serverConfig.callConnectTimeoutMs / 1000., + .receiveTimeout = serverConfig.callPacketTimeoutMs / 1000., + .dataSaving = tgcalls::DataSaving::Never, + .enableP2P = call.is_p2p_allowed(), + .enableAEC = !Platform::IsMac10_7OrGreater(), + .enableNS = true, + .enableAGC = true, + .enableVolumeControl = true, + .maxApiLayer = protocol.vmax_layer().v, + }, + .videoCapture = nullptr, + .stateUpdated = [=](tgcalls::State state) { + crl::on_main(weak, [=] { + handleControllerStateChange(state); + }); + }, + .videoStateUpdated = [=](bool state) { + + }, + .signalBarsUpdated = [=](int count) { + crl::on_main(weak, [=] { + handleControllerBarCountChange(count); + }); + }, + .remoteVideoIsActiveUpdated = [=](bool active) { + }, + .signalingDataEmitted = [=](const std::vector &data) { + const auto bytes = QByteArray( + reinterpret_cast(data.data()), + data.size()); + crl::on_main(weak, [=] { + sendSignalingData(bytes); + }); + }, + }; if (Logs::DebugEnabled()) { auto callLogFolder = cWorkingDir() + qsl("DebugLogs"); auto callLogPath = callLogFolder + qsl("/last_call_log.txt"); auto callLogNative = QDir::toNativeSeparators(callLogPath); #ifdef Q_OS_WIN - config.logPath = callLogNative.toStdWString(); + descriptor.config.logPath = callLogNative.toStdWString(); #else // Q_OS_WIN const auto callLogUtf = QFile::encodeName(callLogNative); - config.logPath.resize(callLogUtf.size()); + descriptor.config.logPath.resize(callLogUtf.size()); ranges::copy(callLogUtf, config.logPath.begin()); #endif // Q_OS_WIN QFile(callLogPath).remove(); QDir().mkpath(callLogFolder); } - auto endpoints = std::vector(); for (const auto &connection : call.vconnections().v) { - AppendEndpoint(endpoints, connection); + AppendEndpoint(descriptor.endpoints, connection); } - auto proxy = TgVoipProxy(); + descriptor.rtcServers = CollectRtcServers(_user); + if (Global::UseProxyForCalls() && (Global::ProxySettings() == MTP::ProxyData::Settings::Enabled)) { const auto &selected = Global::SelectedProxy(); - if (selected.supportsCalls()) { + if (selected.supportsCalls() && !selected.host.isEmpty()) { Assert(selected.type == MTP::ProxyData::Type::Socks5); - proxy.host = selected.host.toStdString(); - proxy.port = selected.port; - proxy.login = selected.user.toStdString(); - proxy.password = selected.password.toStdString(); + descriptor.proxy = std::make_unique(); + descriptor.proxy->host = selected.host.toStdString(); + descriptor.proxy->port = selected.port; + descriptor.proxy->login = selected.user.toStdString(); + descriptor.proxy->password = selected.password.toStdString(); } } - auto encryptionKey = TgVoipEncryptionKey(); - encryptionKey.isOutgoing = (_type == Type::Outgoing); - encryptionKey.value = ranges::view::all( + descriptor.encryptionKey.isOutgoing = (_type == Type::Outgoing); + descriptor.encryptionKey.value = ranges::view::all( _authKey ) | ranges::view::transform([](bytes::type byte) { return static_cast(byte); @@ -623,28 +710,26 @@ void Call::createAndStartController(const MTPDphoneCall &call) { const MTPDphoneCallProtocol &data) { return data.vlibrary_versions().v; }).value(0, MTP_bytes(kDefaultVersion)).v; - _controller = MakeController( - version.toStdString(), - config, - TgVoipPersistentState(), - endpoints, - proxy.host.empty() ? nullptr : &proxy, - TgVoipNetworkType::Unknown, - encryptionKey, - [=](QByteArray data) { sendSignalingData(data); }, - [=](QImage frame) { displayNextFrame(frame); }); - const auto raw = _controller.get(); - raw->setOnStateUpdated([=](TgVoipState state) { - handleControllerStateChange(raw, state); - }); - raw->setOnSignalBarsUpdated([=](int count) { - handleControllerBarCountChange(count); - }); + LOG(("Call Info: Creating instance with version '%1', allowP2P: %2" + ).arg(QString::fromUtf8(version) + ).arg(Logs::b(descriptor.config.enableP2P))); + _instance = tgcalls::Meta::Create( + version.toStdString(), + std::move(descriptor)); + if (!_instance) { + LOG(("Call Error: Wrong library version: %1." + ).arg(QString::fromUtf8(version))); + finish(FinishType::Failed); + return; + } + + const auto raw = _instance.get(); if (_mute) { raw->setMuteMicrophone(_mute); } const auto &settings = Core::App().settings(); + //raw->setIncomingVideoOutput(std::make_shared>()) raw->setAudioOutputDevice( settings.callOutputDeviceID().toStdString()); raw->setAudioInputDevice( @@ -654,32 +739,27 @@ void Call::createAndStartController(const MTPDphoneCall &call) { raw->setAudioOutputDuckingEnabled(settings.callAudioDuckingEnabled()); } -void Call::handleControllerStateChange( - not_null controller, - TgVoipState state) { - // NB! Can be called from an arbitrary thread! - // This can be called from ~VoIPController()! - +void Call::handleControllerStateChange(tgcalls::State state) { switch (state) { - case TgVoipState::WaitInit: { + case tgcalls::State::WaitInit: { DEBUG_LOG(("Call Info: State changed to WaitingInit.")); - setStateQueued(State::WaitingInit); + setState(State::WaitingInit); } break; - case TgVoipState::WaitInitAck: { + case tgcalls::State::WaitInitAck: { DEBUG_LOG(("Call Info: State changed to WaitingInitAck.")); - setStateQueued(State::WaitingInitAck); + setState(State::WaitingInitAck); } break; - case TgVoipState::Established: { + case tgcalls::State::Established: { DEBUG_LOG(("Call Info: State changed to Established.")); - setStateQueued(State::Established); + setState(State::Established); } break; - case TgVoipState::Failed: { - auto error = QString::fromStdString(controller->getLastError()); + case tgcalls::State::Failed: { + auto error = QString::fromStdString(_instance->getLastError()); LOG(("Call Info: State changed to Failed, error: %1.").arg(error)); - setFailedQueued(error); + handleControllerError(error); } break; default: LOG(("Call Error: Unexpected state in handleStateChange: %1" @@ -688,12 +768,7 @@ void Call::handleControllerStateChange( } void Call::handleControllerBarCountChange(int count) { - // NB! Can be called from an arbitrary thread! - // This can be called from ~VoIPController()! - - crl::on_main(this, [=] { - setSignalBarCount(count); - }); + setSignalBarCount(count); } void Call::setSignalBarCount(int count) { @@ -794,28 +869,28 @@ void Call::setState(State state) { } void Call::setCurrentAudioDevice(bool input, std::string deviceID) { - if (_controller) { + if (_instance) { if (input) { - _controller->setAudioInputDevice(deviceID); + _instance->setAudioInputDevice(deviceID); } else { - _controller->setAudioOutputDevice(deviceID); + _instance->setAudioOutputDevice(deviceID); } } } void Call::setAudioVolume(bool input, float level) { - if (_controller) { + if (_instance) { if (input) { - _controller->setInputVolume(level); + _instance->setInputVolume(level); } else { - _controller->setOutputVolume(level); + _instance->setOutputVolume(level); } } } void Call::setAudioDuckingEnabled(bool enabled) { - if (_controller) { - _controller->setAudioOutputDuckingEnabled(enabled); + if (_instance) { + _instance->setAudioOutputDuckingEnabled(enabled); } } @@ -846,7 +921,7 @@ void Call::finish(FinishType type, const MTPPhoneCallDiscardReason &reason) { setState(hangupState); auto duration = getDurationMs() / 1000; - auto connectionId = _controller ? _controller->getPreferredRelayId() : 0; + auto connectionId = _instance ? _instance->getPreferredRelayId() : 0; _finishByTimeoutTimer.call(kHangupTimeoutMs, [this, finalState] { setState(finalState); }); _api.request(MTPphone_DiscardCall( MTP_flags(0), @@ -902,9 +977,13 @@ void Call::handleControllerError(const QString &error) { } void Call::destroyController() { - if (_controller) { + if (_instance) { + AssertIsDebug(); + const auto state = _instance->stop(); + LOG(("CALL_LOG: %1").arg(QString::fromStdString(state.debugLog))); + DEBUG_LOG(("Call Info: Destroying call controller..")); - _controller.reset(); + _instance.reset(); DEBUG_LOG(("Call Info: Call controller destroyed.")); } setSignalBarCount(kSignalBarFinished); @@ -915,7 +994,7 @@ Call::~Call() { } void UpdateConfig(const std::string &data) { - TgVoip::setGlobalServerConfig(data); + tgcalls::SetLegacyGlobalServerConfig(data); } } // namespace Calls diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index 582f72fa16..eb2eb83287 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -19,12 +19,13 @@ class Track; } // namespace Audio } // namespace Media -enum class TgVoipState; +namespace tgcalls { +class Instance; +enum class State; +} // namespace tgcalls namespace Calls { -class Controller; - struct DhConfig { int32 version = 0; int32 g = 0; @@ -153,9 +154,7 @@ private: void displayNextFrame(QImage frame); void generateModExpFirst(bytes::const_span randomSeed); - void handleControllerStateChange( - not_null controller, - TgVoipState state); + void handleControllerStateChange(tgcalls::State state); void handleControllerBarCountChange(int count); void createAndStartController(const MTPDphoneCall &call); @@ -202,7 +201,7 @@ private: uint64 _accessHash = 0; uint64 _keyFingerprint = 0; - std::unique_ptr _controller; + std::unique_ptr _instance; std::unique_ptr _waitingTrack; diff --git a/Telegram/SourceFiles/main/main_app_config.cpp b/Telegram/SourceFiles/main/main_app_config.cpp index bf6648a9ae..9311eb6a04 100644 --- a/Telegram/SourceFiles/main/main_app_config.cpp +++ b/Telegram/SourceFiles/main/main_app_config.cpp @@ -117,6 +117,7 @@ std::vector AppConfig::getStringArray( return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonArray &data) { auto result = std::vector(); + result.reserve(data.vvalue().v.size()); for (const auto &entry : data.vvalue().v) { if (entry.type() != mtpc_jsonString) { return std::move(fallback); @@ -130,6 +131,36 @@ std::vector AppConfig::getStringArray( }); } +std::vector> AppConfig::getStringMapArray( + const QString &key, + std::vector> &&fallback) const { + return getValue(key, [&](const MTPJSONValue &value) { + return value.match([&](const MTPDjsonArray &data) { + auto result = std::vector>(); + result.reserve(data.vvalue().v.size()); + for (const auto &entry : data.vvalue().v) { + if (entry.type() != mtpc_jsonObject) { + return std::move(fallback); + } + auto element = std::map(); + for (const auto &field : entry.c_jsonObject().vvalue().v) { + const auto &data = field.c_jsonObjectValue(); + if (data.vvalue().type() != mtpc_jsonString) { + return std::move(fallback); + } + element.emplace( + qs(data.vkey()), + qs(data.vvalue().c_jsonString().vvalue())); + } + result.push_back(std::move(element)); + } + return result; + }, [&](const auto &data) { + return std::move(fallback); + }); + }); +} + bool AppConfig::suggestionCurrent(const QString &key) const { return !_dismissedSuggestions.contains(key) && ranges::contains( diff --git a/Telegram/SourceFiles/main/main_app_config.h b/Telegram/SourceFiles/main/main_app_config.h index 176d73c586..1235b7b402 100644 --- a/Telegram/SourceFiles/main/main_app_config.h +++ b/Telegram/SourceFiles/main/main_app_config.h @@ -25,6 +25,8 @@ public: return getString(key, fallback); } else if constexpr (std::is_same_v>) { return getStringArray(key, std::move(fallback)); + } else if constexpr (std::is_same_v>>) { + return getStringMapArray(key, std::move(fallback)); } else if constexpr (std::is_same_v) { return getBool(key, fallback); } @@ -60,6 +62,9 @@ private: [[nodiscard]] std::vector getStringArray( const QString &key, std::vector &&fallback) const; + [[nodiscard]] std::vector> getStringMapArray( + const QString &key, + std::vector> &&fallback) const; const not_null _account; std::optional _api; diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls new file mode 160000 index 0000000000..ccba258805 --- /dev/null +++ b/Telegram/ThirdParty/tgcalls @@ -0,0 +1 @@ +Subproject commit ccba258805478783804cf273ff8c5edffd9f009a diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake new file mode 100644 index 0000000000..3b6fc933d4 --- /dev/null +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -0,0 +1,102 @@ +# This file is part of Telegram Desktop, +# the official desktop application for the Telegram messaging service. +# +# For license and copyright information please follow this link: +# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL + +add_library(lib_tgcalls STATIC) +init_target(lib_tgcalls) +add_library(tdesktop::lib_tgcalls ALIAS lib_tgcalls) + +set(tgcalls_dir ${third_party_loc}/tgcalls) +set(tgcalls_loc ${tgcalls_dir}/tgcalls) + +nice_target_sources(lib_tgcalls ${tgcalls_loc} +PRIVATE + Manager.cpp + Manager.h + MediaManager.cpp + MediaManager.h + NetworkManager.cpp + NetworkManager.h + Instance.cpp + Instance.h + InstanceImpl.cpp + InstanceImpl.h + ThreadLocalObject.h + VideoCaptureInterface.cpp + VideoCaptureInterface.h + VideoCaptureInterfaceImpl.cpp + VideoCaptureInterfaceImpl.h + VideoCapturerInterface.h + platform/PlatformInterface.h + + # Windows + platform/windows/WindowsInterface.cpp + platform/windows/WindowsInterface.h + platform/windows/VideoCapturerInterfaceImpl.cpp + platform/windows/VideoCapturerInterfaceImpl.h + + # iOS / macOS + platform/darwin/DarwinInterface.h + platform/darwin/DarwinInterface.mm + platform/darwin/TGRTCDefaultVideoDecoderFactory.h + platform/darwin/TGRTCDefaultVideoDecoderFactory.mm + platform/darwin/TGRTCDefaultVideoEncoderFactory.h + platform/darwin/TGRTCDefaultVideoEncoderFactory.mm + platform/darwin/TGRTCVideoDecoderH265.h + platform/darwin/TGRTCVideoDecoderH265.mm + platform/darwin/TGRTCVideoEncoderH265.h + platform/darwin/TGRTCVideoEncoderH265.mm + platform/darwin/VideoCameraCapturer.h + platform/darwin/VideoCameraCapturer.mm + platform/darwin/VideoCapturerInterfaceImpl.h + platform/darwin/VideoCapturerInterfaceImpl.mm + platform/darwin/VideoMetalView.h + platform/darwin/VideoMetalView.mm + + # Linux + + # POSIX +) + +if (WIN32) + target_compile_definitions(lib_tgcalls + PRIVATE + TARGET_OS_WIN + ) +endif() + +target_include_directories(lib_tgcalls +PUBLIC + ${tgcalls_dir} +PRIVATE + ${tgcalls_loc} +) + +target_link_libraries(lib_tgcalls +PRIVATE + desktop-app::external_webrtc +) + +add_library(lib_tgcalls_legacy STATIC) +init_target(lib_tgcalls_legacy) +add_library(tdesktop::lib_tgcalls_legacy ALIAS lib_tgcalls_legacy) + +nice_target_sources(lib_tgcalls_legacy ${tgcalls_loc} +PRIVATE + legacy/InstanceImplLegacy.cpp + legacy/InstanceImplLegacy.h +) + +target_include_directories(lib_tgcalls_legacy +PRIVATE + ${tgcalls_loc} +) + +target_link_libraries(lib_tgcalls_legacy +PRIVATE + tdesktop::lib_tgcalls + tdesktop::lib_tgvoip + desktop-app::external_openssl +) diff --git a/Telegram/cmake/lib_tgvoip.cmake b/Telegram/cmake/lib_tgvoip.cmake index 50748c3245..27e74d07a5 100644 --- a/Telegram/cmake/lib_tgvoip.cmake +++ b/Telegram/cmake/lib_tgvoip.cmake @@ -48,8 +48,6 @@ else() OpusEncoder.cpp OpusEncoder.h threading.h - TgVoip.cpp - TgVoip.h VoIPController.cpp VoIPGroupController.cpp VoIPController.h diff --git a/Telegram/lib_webrtc b/Telegram/lib_webrtc index eb5be18405..d3d96130ba 160000 --- a/Telegram/lib_webrtc +++ b/Telegram/lib_webrtc @@ -1 +1 @@ -Subproject commit eb5be18405d47a226f6a197280176f82b3e903bd +Subproject commit d3d96130ba245e985c79c9040459b548416efdf8 diff --git a/docs/building-msvc.md b/docs/building-msvc.md index 4b80dfe908..d7beba696c 100644 --- a/docs/building-msvc.md +++ b/docs/building-msvc.md @@ -163,6 +163,16 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath*** jom -j4 install cd .. + mkdir webrtc + cd webrtc + copy ..\patches\webrtc.gclient .gclient + git clone https://github.com/open-webrtc-toolkit/owt-deps-webrtc src + gclient sync + cd src + ..\..\..\tdesktop\Telegram\lib_webrtc\gn_build_webrtc.bat + ninja -C out/Debug webrtc test:platform_video_capturer test:video_test_common + cd .. + ## Build the project Go to ***BuildPath*\\tdesktop\\Telegram** and run (using [your **api_id** and **api_hash**](#obtain-your-api-credentials))