Checkpoint WebRTC Voice
parent
19b808316b
commit
bf58173656
|
|
@ -506,6 +506,14 @@
|
|||
<boolean>false</boolean>
|
||||
</map>
|
||||
|
||||
<key>VoiceSignalingRequest</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
<string>llsd</string>
|
||||
<key>trusted-sender</key>
|
||||
<boolean>false</boolean>
|
||||
</map>
|
||||
|
||||
<!-- Server to client -->
|
||||
<key>RequiredVoiceVersion</key>
|
||||
<map>
|
||||
|
|
@ -688,6 +696,9 @@
|
|||
|
||||
<key>ProvisionVoiceAccountRequest</key>
|
||||
<boolean>false</boolean>
|
||||
|
||||
<key>VoiceSignalingRequest</key>
|
||||
<boolean>false</boolean>
|
||||
|
||||
<key>RemoteParcelRequest</key>
|
||||
<boolean>false</boolean>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
|
|||
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llwebrtc)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llwindow)
|
||||
add_subdirectory(${LIBS_OPEN_PREFIX}llxml)
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ set(cmake_SOURCE_FILES
|
|||
ViewerMiscLibs.cmake
|
||||
VisualLeakDetector.cmake
|
||||
LibVLCPlugin.cmake
|
||||
WebRTC.cmake
|
||||
XmlRpcEpi.cmake
|
||||
xxHash.cmake
|
||||
ZLIBNG.cmake
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
# -*- cmake -*-
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# -*- cmake -*-
|
||||
include(CMakeCopyIfDifferent)
|
||||
|
||||
include(Linking)
|
||||
|
||||
include_guard()
|
||||
|
||||
set(WEBRTC_ROOT ${CMAKE_BINARY_DIR}/../../webrtc/src)
|
||||
file(COPY ${WEBRTC_ROOT}/out/Default/obj/webrtc.lib
|
||||
DESTINATION ${CMAKE_BINARY_DIR}/packages/lib/release
|
||||
)
|
||||
set(WEBRTC_INCLUDE_DIR ${CMAKE_BINARY_DIR}/packages/include/webrtc)
|
||||
file(MAKE_DIRECTORY ${WEBRTC_INCLUDE_DIR})
|
||||
|
||||
file(COPY ${WEBRTC_ROOT}/api
|
||||
${WEBRTC_ROOT}/media/base
|
||||
${WEBRTC_ROOT}/media/engine
|
||||
${WEBRTC_ROOT}/rtc_base
|
||||
${WEBRTC_ROOT}/pc
|
||||
${WEBRTC_ROOT}/p2p
|
||||
${WEBRTC_ROOT}/call
|
||||
${WEBRTC_ROOT}/media
|
||||
${WEBRTC_ROOT}/system_wrappers
|
||||
${WEBRTC_ROOT}/common_video
|
||||
${WEBRTC_ROOT}/video
|
||||
${WEBRTC_ROOT}/common_audio
|
||||
${WEBRTC_ROOT}/logging
|
||||
${WEBRTC_ROOT}/third_party/abseil-cpp/absl
|
||||
DESTINATION ${WEBRTC_INCLUDE_DIR}
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
)
|
||||
|
||||
add_library(ll::webrtc STATIC IMPORTED)
|
||||
|
||||
if (LINUX)
|
||||
target_link_libraries( ll::webrtc INTERFACE ../webrtc/src/obj/Default/webrtc)
|
||||
elseif (DARWIN)
|
||||
target_link_libraries( ll::webrtc INTERFACE ../webrtc/src/obj/Default/webrtc)
|
||||
elseif (WINDOWS)
|
||||
set_target_properties( ll::webrtc PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/packages/lib/release/webrtc.lib)
|
||||
target_link_libraries( ll::webrtc INTERFACE ${CMAKE_BINARY_DIR}/packages/lib/release/webrtc.lib)
|
||||
endif (LINUX)
|
||||
target_include_directories( ll::webrtc INTERFACE "${WEBRTC_INCLUDE_DIR}")
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# some webrtc headers require C++ 20
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
set(CMAKE_GENERATOR_TOOLSET "clang_cl_x64")
|
||||
|
||||
include(00-Common)
|
||||
include(Linking)
|
||||
include(WebRTC)
|
||||
|
||||
project(llwebrtc)
|
||||
|
||||
message(STATUS "C Compiler executable: ${CMAKE_C_COMPILER}")
|
||||
message(STATUS "CXX Compiler executable: ${CMAKE_CXX_COMPILER}")
|
||||
message(STATUS "Linker executable: ${CMAKE_LINKER}")
|
||||
message(STATUS "SharedLib: ${SHARED_LIB_STAGING_DIR}")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
|
||||
|
||||
set(llwebrtc_SOURCE_FILES
|
||||
llwebrtc.cpp
|
||||
)
|
||||
|
||||
set(llwebrtc_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
llwebrtc.h
|
||||
llwebrtc_impl.h
|
||||
)
|
||||
|
||||
list(APPEND llwebrtc_SOURCE_FILES ${llwebrtc_HEADER_FILES})
|
||||
|
||||
add_library (llwebrtc SHARED ${llwebrtc_SOURCE_FILES})
|
||||
|
||||
set_target_properties(llwebrtc PROPERTIES PUBLIC_HEADER llwebrtc.h)
|
||||
|
||||
target_link_libraries(llwebrtc PRIVATE ll::webrtc
|
||||
secur32
|
||||
winmm
|
||||
dmoguids
|
||||
wmcodecdspuuid
|
||||
msdmo
|
||||
strmiids
|
||||
iphlpapi)
|
||||
target_include_directories( llwebrtc INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
set_property(TARGET llwebrtc PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDebug")
|
||||
|
||||
install(TARGETS llwebrtc RUNTIME DESTINATION "${CMAKE_BINARY_DIR}/sharedlibs/RelWithDebInfo")
|
||||
|
||||
# Add tests
|
||||
if (LL_TESTS)
|
||||
endif (LL_TESTS)
|
||||
|
|
@ -0,0 +1,486 @@
|
|||
/**
|
||||
* @file llaccordionctrl.cpp
|
||||
* @brief Accordion panel implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2023, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llwebrtc_impl.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "api/audio_codecs/audio_decoder_factory.h"
|
||||
#include "api/audio_codecs/audio_encoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/media_stream_track.h"
|
||||
|
||||
namespace llwebrtc
|
||||
{
|
||||
|
||||
void LLWebRTCImpl::init()
|
||||
{
|
||||
mAnswerReceived = false;
|
||||
rtc::InitializeSSL();
|
||||
mTaskQueueFactory = webrtc::CreateDefaultTaskQueueFactory();
|
||||
|
||||
mNetworkThread = rtc::Thread::CreateWithSocketServer();
|
||||
mNetworkThread->SetName("WebRTCNetworkThread", nullptr);
|
||||
mNetworkThread->Start();
|
||||
mWorkerThread = rtc::Thread::Create();
|
||||
mWorkerThread->SetName("WebRTCWorkerThread", nullptr);
|
||||
mWorkerThread->Start();
|
||||
mSignalingThread = rtc::Thread::Create();
|
||||
mSignalingThread->SetName("WebRTCSignalingThread", nullptr);
|
||||
mSignalingThread->Start();
|
||||
|
||||
mSignalingThread->PostTask(
|
||||
[this]()
|
||||
{
|
||||
mDeviceModule = webrtc::CreateAudioDeviceWithDataObserver(webrtc::AudioDeviceModule::AudioLayer::kPlatformDefaultAudio,
|
||||
mTaskQueueFactory.get(),
|
||||
std::unique_ptr<webrtc::AudioDeviceDataObserver>(this));
|
||||
mDeviceModule->Init();
|
||||
updateDevices();
|
||||
});
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::refreshDevices()
|
||||
{
|
||||
mSignalingThread->PostTask([this]() { updateDevices(); });
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setDevicesObserver(LLWebRTCDevicesObserver *observer) { mVoiceDevicesObserverList.emplace_back(observer); }
|
||||
|
||||
void LLWebRTCImpl::unsetDevicesObserver(LLWebRTCDevicesObserver *observer)
|
||||
{
|
||||
std::vector<LLWebRTCDevicesObserver *>::iterator it =
|
||||
std::find(mVoiceDevicesObserverList.begin(), mVoiceDevicesObserverList.end(), observer);
|
||||
if (it != mVoiceDevicesObserverList.end())
|
||||
{
|
||||
mVoiceDevicesObserverList.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setCaptureDevice(const std::string &id)
|
||||
{
|
||||
mSignalingThread->PostTask(
|
||||
[this, id]()
|
||||
{
|
||||
int16_t captureDeviceCount = mDeviceModule->RecordingDevices();
|
||||
for (int16_t index = 0; index < captureDeviceCount; index++)
|
||||
{
|
||||
char name[webrtc::kAdmMaxDeviceNameSize];
|
||||
char guid[webrtc::kAdmMaxGuidSize];
|
||||
mDeviceModule->RecordingDeviceName(index, name, guid);
|
||||
if (id == guid || id == name)
|
||||
{
|
||||
mDeviceModule->SetRecordingDevice(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setRenderDevice(const std::string &id)
|
||||
{
|
||||
mSignalingThread->PostTask(
|
||||
[this, id]()
|
||||
{
|
||||
int16_t renderDeviceCount = mDeviceModule->RecordingDevices();
|
||||
for (int16_t index = 0; index < renderDeviceCount; index++)
|
||||
{
|
||||
char name[webrtc::kAdmMaxDeviceNameSize];
|
||||
char guid[webrtc::kAdmMaxGuidSize];
|
||||
mDeviceModule->PlayoutDeviceName(index, name, guid);
|
||||
if (id == guid || id == name)
|
||||
{
|
||||
mDeviceModule->SetPlayoutDevice(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::updateDevices()
|
||||
{
|
||||
int16_t renderDeviceCount = mDeviceModule->PlayoutDevices();
|
||||
LLWebRTCVoiceDeviceList renderDeviceList;
|
||||
for (int16_t index = 0; index < renderDeviceCount; index++)
|
||||
{
|
||||
char name[webrtc::kAdmMaxDeviceNameSize];
|
||||
char guid[webrtc::kAdmMaxGuidSize];
|
||||
mDeviceModule->PlayoutDeviceName(index, name, guid);
|
||||
renderDeviceList.emplace_back(name, guid);
|
||||
}
|
||||
for (auto &observer : mVoiceDevicesObserverList)
|
||||
{
|
||||
observer->OnRenderDevicesChanged(renderDeviceList);
|
||||
}
|
||||
|
||||
int16_t captureDeviceCount = mDeviceModule->RecordingDevices();
|
||||
LLWebRTCVoiceDeviceList captureDeviceList;
|
||||
for (int16_t index = 0; index < captureDeviceCount; index++)
|
||||
{
|
||||
char name[webrtc::kAdmMaxDeviceNameSize];
|
||||
char guid[webrtc::kAdmMaxGuidSize];
|
||||
mDeviceModule->RecordingDeviceName(index, name, guid);
|
||||
captureDeviceList.emplace_back(name, guid);
|
||||
}
|
||||
for (auto &observer : mVoiceDevicesObserverList)
|
||||
{
|
||||
observer->OnCaptureDevicesChanged(captureDeviceList);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setTuningMode(bool enable)
|
||||
{
|
||||
mSignalingThread->PostTask(
|
||||
[this, enable]()
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
mDeviceModule->InitMicrophone();
|
||||
mDeviceModule->InitRecording();
|
||||
mDeviceModule->StartRecording();
|
||||
mDeviceModule->SetMicrophoneMute(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDeviceModule->StopRecording();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
double LLWebRTCImpl::getTuningMicrophoneEnergy() { return mTuningEnergy; }
|
||||
|
||||
void LLWebRTCImpl::OnCaptureData(const void *audio_samples,
|
||||
const size_t num_samples,
|
||||
const size_t bytes_per_sample,
|
||||
const size_t num_channels,
|
||||
const uint32_t samples_per_sec)
|
||||
{
|
||||
if (bytes_per_sample != 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double energy = 0;
|
||||
const short *samples = (const short *) audio_samples;
|
||||
for (size_t index = 0; index < num_samples * num_channels; index++)
|
||||
{
|
||||
double sample = (static_cast<double>(samples[index]) / (double) 32768);
|
||||
energy += sample * sample;
|
||||
}
|
||||
mTuningEnergy = std::sqrt(energy);
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::OnRenderData(const void *audio_samples,
|
||||
const size_t num_samples,
|
||||
const size_t bytes_per_sample,
|
||||
const size_t num_channels,
|
||||
const uint32_t samples_per_sec)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// LLWebRTCSignalInterface
|
||||
//
|
||||
|
||||
void LLWebRTCImpl::setSignalingObserver(LLWebRTCSignalingObserver *observer) { mSignalingObserverList.emplace_back(observer); }
|
||||
|
||||
void LLWebRTCImpl::unsetSignalingObserver(LLWebRTCSignalingObserver *observer)
|
||||
{
|
||||
std::vector<LLWebRTCSignalingObserver *>::iterator it =
|
||||
std::find(mSignalingObserverList.begin(), mSignalingObserverList.end(), observer);
|
||||
if (it != mSignalingObserverList.end())
|
||||
{
|
||||
mSignalingObserverList.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLWebRTCImpl::initializeConnection()
|
||||
{
|
||||
RTC_DCHECK(!mPeerConnection);
|
||||
RTC_DCHECK(!mPeerConnectionFactory);
|
||||
mAnswerReceived = false;
|
||||
mPeerConnectionFactory = webrtc::CreatePeerConnectionFactory(mNetworkThread.get(),
|
||||
mWorkerThread.get(),
|
||||
mSignalingThread.get(),
|
||||
nullptr /* default_adm */,
|
||||
webrtc::CreateBuiltinAudioEncoderFactory(),
|
||||
webrtc::CreateBuiltinAudioDecoderFactory(),
|
||||
nullptr /* video_encoder_factory */,
|
||||
nullptr /* video_decoder_factory */,
|
||||
nullptr /* audio_mixer */,
|
||||
nullptr /* audio_processing */);
|
||||
|
||||
if (!mPeerConnectionFactory)
|
||||
{
|
||||
shutdownConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||
config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
|
||||
webrtc::PeerConnectionInterface::IceServer server;
|
||||
server.uri = "stun:stun.l.google.com:19302";
|
||||
// config.servers.push_back(server);
|
||||
// server.uri = "stun:stun1.l.google.com:19302";
|
||||
// config.servers.push_back(server);
|
||||
// server.uri = "stun:stun2.l.google.com:19302";
|
||||
// config.servers.push_back(server);
|
||||
// server.uri = "stun:stun3.l.google.com:19302";
|
||||
// config.servers.push_back(server);
|
||||
// server.uri = "stun:stun4.l.google.com:19302";
|
||||
// config.servers.push_back(server);
|
||||
|
||||
webrtc::PeerConnectionDependencies pc_dependencies(this);
|
||||
auto error_or_peer_connection = mPeerConnectionFactory->CreatePeerConnectionOrError(config, std::move(pc_dependencies));
|
||||
if (error_or_peer_connection.ok())
|
||||
{
|
||||
mPeerConnection = std::move(error_or_peer_connection.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
shutdownConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->signaling_state();
|
||||
|
||||
cricket::AudioOptions audioOptions;
|
||||
audioOptions.auto_gain_control = true;
|
||||
audioOptions.echo_cancellation = true;
|
||||
audioOptions.noise_suppression = true;
|
||||
|
||||
rtc::scoped_refptr<webrtc::MediaStreamInterface> stream = mPeerConnectionFactory->CreateLocalMediaStream("SLStream");
|
||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
||||
mPeerConnectionFactory->CreateAudioTrack("SLAudio", mPeerConnectionFactory->CreateAudioSource(cricket::AudioOptions()).get()));
|
||||
audio_track->set_enabled(true);
|
||||
stream->AddTrack(audio_track);
|
||||
|
||||
mPeerConnection->AddTrack(audio_track, {"SLStream"});
|
||||
mPeerConnection->SetLocalDescription(rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface>(this));
|
||||
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->signaling_state();
|
||||
|
||||
return mPeerConnection != nullptr;
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::shutdownConnection()
|
||||
{
|
||||
mPeerConnection = nullptr;
|
||||
mPeerConnectionFactory = nullptr;
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::AnswerAvailable(const std::string &sdp)
|
||||
{
|
||||
mSignalingThread->PostTask(
|
||||
[this, sdp]()
|
||||
{
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->peer_connection_state();
|
||||
mPeerConnection->SetRemoteDescription(webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp),
|
||||
rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface>(this));
|
||||
mAnswerReceived = true;
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
for (auto &candidate : mCachedIceCandidates)
|
||||
{
|
||||
LLWebRTCIceCandidate ice_candidate;
|
||||
ice_candidate.candidate = candidate->candidate().ToString();
|
||||
ice_candidate.mline_index = candidate->sdp_mline_index();
|
||||
ice_candidate.sdp_mid = candidate->sdp_mid();
|
||||
observer->OnIceCandidate(ice_candidate);
|
||||
}
|
||||
mCachedIceCandidates.clear();
|
||||
if (mPeerConnection->ice_gathering_state() == webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringComplete)
|
||||
{
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
observer->OnIceGatheringState(llwebrtc::LLWebRTCSignalingObserver::IceGatheringState::ICE_GATHERING_COMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::setMute(bool mute)
|
||||
{
|
||||
mSignalingThread->PostTask(
|
||||
[this,mute]()
|
||||
{
|
||||
auto senders = mPeerConnection->GetSenders();
|
||||
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << (mute ? "disabling" : "enabling") << " streams count "
|
||||
<< senders.size();
|
||||
|
||||
for (auto& sender : senders)
|
||||
{
|
||||
sender->track()->set_enabled(!mute);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// PeerConnectionObserver implementation.
|
||||
//
|
||||
|
||||
void LLWebRTCImpl::OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
|
||||
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams)
|
||||
{
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << receiver->id();
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver)
|
||||
{
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << receiver->id();
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state)
|
||||
{
|
||||
LLWebRTCSignalingObserver::IceGatheringState webrtc_new_state = LLWebRTCSignalingObserver::IceGatheringState::ICE_GATHERING_NEW;
|
||||
switch (new_state)
|
||||
{
|
||||
case webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringNew:
|
||||
webrtc_new_state = LLWebRTCSignalingObserver::IceGatheringState::ICE_GATHERING_NEW;
|
||||
break;
|
||||
case webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringGathering:
|
||||
webrtc_new_state = LLWebRTCSignalingObserver::IceGatheringState::ICE_GATHERING_GATHERING;
|
||||
break;
|
||||
case webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringComplete:
|
||||
webrtc_new_state = LLWebRTCSignalingObserver::IceGatheringState::ICE_GATHERING_COMPLETE;
|
||||
break;
|
||||
default:
|
||||
RTC_LOG(LS_ERROR) << __FUNCTION__ << " Bad Ice Gathering State" << new_state;
|
||||
webrtc_new_state = LLWebRTCSignalingObserver::IceGatheringState::ICE_GATHERING_NEW;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAnswerReceived)
|
||||
{
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
observer->OnIceGatheringState(webrtc_new_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called any time the PeerConnectionState changes.
|
||||
void LLWebRTCImpl::OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state)
|
||||
{
|
||||
RTC_LOG(LS_ERROR) << __FUNCTION__ << " Peer Connection State Change " << new_state;
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::OnIceCandidate(const webrtc::IceCandidateInterface *candidate)
|
||||
{
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
|
||||
|
||||
if (!candidate)
|
||||
{
|
||||
RTC_LOG(LS_ERROR) << __FUNCTION__ << " No Ice Candidate Given";
|
||||
return;
|
||||
}
|
||||
if (mAnswerReceived)
|
||||
{
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
LLWebRTCIceCandidate ice_candidate;
|
||||
ice_candidate.candidate = candidate->candidate().ToString();
|
||||
ice_candidate.mline_index = candidate->sdp_mline_index();
|
||||
ice_candidate.sdp_mid = candidate->sdp_mid();
|
||||
observer->OnIceCandidate(ice_candidate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mCachedIceCandidates.push_back(
|
||||
webrtc::CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(), candidate->candidate()));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// CreateSessionDescriptionObserver implementation.
|
||||
//
|
||||
void LLWebRTCImpl::OnSuccess(webrtc::SessionDescriptionInterface *desc)
|
||||
{
|
||||
std::string sdp;
|
||||
desc->ToString(&sdp);
|
||||
RTC_LOG(LS_INFO) << sdp;
|
||||
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->signaling_state();
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
observer->OnOfferAvailable(sdp);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWebRTCImpl::OnFailure(webrtc::RTCError error) { RTC_LOG(LS_ERROR) << ToString(error.type()) << ": " << error.message(); }
|
||||
|
||||
//
|
||||
// SetRemoteDescriptionObserverInterface implementation.
|
||||
//
|
||||
void LLWebRTCImpl::OnSetRemoteDescriptionComplete(webrtc::RTCError error)
|
||||
{
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->signaling_state();
|
||||
if (!error.ok())
|
||||
{
|
||||
RTC_LOG(LS_ERROR) << ToString(error.type()) << ": " << error.message();
|
||||
return;
|
||||
}
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
observer->OnAudioEstablished(this);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// SetLocalDescriptionObserverInterface implementation.
|
||||
//
|
||||
void LLWebRTCImpl::OnSetLocalDescriptionComplete(webrtc::RTCError error)
|
||||
{
|
||||
RTC_LOG(LS_INFO) << __FUNCTION__ << " " << mPeerConnection->signaling_state();
|
||||
if (!error.ok())
|
||||
{
|
||||
RTC_LOG(LS_ERROR) << ToString(error.type()) << ": " << error.message();
|
||||
return;
|
||||
}
|
||||
auto desc = mPeerConnection->pending_local_description();
|
||||
std::string sdp;
|
||||
desc->ToString(&sdp);
|
||||
for (auto &observer : mSignalingObserverList)
|
||||
{
|
||||
observer->OnOfferAvailable(sdp);
|
||||
}
|
||||
}
|
||||
|
||||
rtc::RefCountedObject<LLWebRTCImpl> *gWebRTCImpl = nullptr;
|
||||
LLWebRTCDeviceInterface *getDeviceInterface() { return gWebRTCImpl; }
|
||||
LLWebRTCSignalInterface *getSignalingInterface() { return gWebRTCImpl; }
|
||||
|
||||
void init()
|
||||
{
|
||||
gWebRTCImpl = new rtc::RefCountedObject<LLWebRTCImpl>();
|
||||
gWebRTCImpl->AddRef();
|
||||
gWebRTCImpl->init();
|
||||
}
|
||||
} // namespace llwebrtc
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* @file llaccordionctrl.cpp
|
||||
* @brief Accordion panel implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2023, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLWEBRTC_H
|
||||
#define LLWEBRTC_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#ifdef LL_MAKEDLL
|
||||
#ifdef WEBRTC_WIN
|
||||
#define LLSYMEXPORT __declspec(dllexport)
|
||||
#elif WEBRTC_LINUX
|
||||
#define LLSYMEXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define LLSYMEXPORT /**/
|
||||
#endif
|
||||
#else
|
||||
#define LLSYMEXPORT /**/
|
||||
#endif // LL_MAKEDLL
|
||||
|
||||
namespace llwebrtc
|
||||
{
|
||||
LLSYMEXPORT void init();
|
||||
|
||||
struct LLWebRTCIceCandidate
|
||||
{
|
||||
std::string candidate;
|
||||
std::string sdp_mid;
|
||||
int mline_index;
|
||||
};
|
||||
|
||||
class LLWebRTCVoiceDevice
|
||||
{
|
||||
public:
|
||||
std::string display_name; // friendly value for the user
|
||||
std::string id; // internal value for selection
|
||||
|
||||
LLWebRTCVoiceDevice(const std::string &display_name, const std::string &id) :
|
||||
display_name(display_name),
|
||||
id(id) {};
|
||||
};
|
||||
|
||||
typedef std::vector<LLWebRTCVoiceDevice> LLWebRTCVoiceDeviceList;
|
||||
|
||||
class LLWebRTCDevicesObserver
|
||||
{
|
||||
public:
|
||||
virtual void OnRenderDevicesChanged(const LLWebRTCVoiceDeviceList &render_devices) = 0;
|
||||
virtual void OnCaptureDevicesChanged(const LLWebRTCVoiceDeviceList &capture_devices) = 0;
|
||||
};
|
||||
|
||||
class LLWebRTCDeviceInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void refreshDevices() = 0;
|
||||
|
||||
virtual void setCaptureDevice(const std::string& id) = 0;
|
||||
virtual void setRenderDevice(const std::string& id) = 0;
|
||||
|
||||
virtual void setDevicesObserver(LLWebRTCDevicesObserver *observer) = 0;
|
||||
virtual void unsetDevicesObserver(LLWebRTCDevicesObserver *observer) = 0;
|
||||
|
||||
virtual void setTuningMode(bool enable) = 0;
|
||||
virtual double getTuningMicrophoneEnergy() = 0;
|
||||
};
|
||||
|
||||
class LLWebRTCAudioInterface
|
||||
{
|
||||
public:
|
||||
virtual void setMute(bool mute) = 0;
|
||||
};
|
||||
|
||||
class LLWebRTCSignalingObserver
|
||||
{
|
||||
public:
|
||||
enum IceGatheringState{
|
||||
ICE_GATHERING_NEW,
|
||||
ICE_GATHERING_GATHERING,
|
||||
ICE_GATHERING_COMPLETE
|
||||
};
|
||||
virtual void OnIceGatheringState(IceGatheringState state) = 0;
|
||||
virtual void OnIceCandidate(const LLWebRTCIceCandidate& candidate) = 0;
|
||||
virtual void OnOfferAvailable(const std::string& sdp) = 0;
|
||||
virtual void OnAudioEstablished(LLWebRTCAudioInterface *audio_interface) = 0;
|
||||
};
|
||||
|
||||
class LLWebRTCSignalInterface
|
||||
{
|
||||
public:
|
||||
virtual void setSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
|
||||
virtual void unsetSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
|
||||
|
||||
virtual bool initializeConnection() = 0;
|
||||
virtual void shutdownConnection() = 0;
|
||||
virtual void AnswerAvailable(const std::string &sdp) = 0;
|
||||
};
|
||||
|
||||
LLSYMEXPORT LLWebRTCDeviceInterface* getDeviceInterface();
|
||||
LLSYMEXPORT LLWebRTCSignalInterface* getSignalingInterface();
|
||||
}
|
||||
|
||||
#endif // LLWEBRTC_H
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* @file llaccordionctrl.cpp
|
||||
* @brief Accordion panel implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2023, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LLWEBRTC_IMPL_H
|
||||
#define LLWEBRTC_IMPL_H
|
||||
|
||||
#define LL_MAKEDLL
|
||||
#define WEBRTC_WIN 1
|
||||
#include "llwebrtc.h"
|
||||
// WebRTC Includes
|
||||
#ifdef WEBRTC_WIN
|
||||
#pragma warning(disable : 4996)
|
||||
#endif // WEBRTC_WIN
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/ref_count.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
#include "rtc_base/ssl_adapter.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/media_stream_interface.h"
|
||||
#include "api/create_peerconnection_factory.h"
|
||||
#include "modules/audio_device/include/audio_device.h"
|
||||
#include "modules/audio_device/include/audio_device_data_observer.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
#include "api/task_queue/task_queue_factory.h"
|
||||
#include "api/task_queue/default_task_queue_factory.h"
|
||||
#include "modules/audio_device/include/audio_device_defines.h"
|
||||
|
||||
|
||||
namespace llwebrtc
|
||||
{
|
||||
|
||||
class LLWebRTCImpl : public LLWebRTCDeviceInterface,
|
||||
public LLWebRTCSignalInterface,
|
||||
public LLWebRTCAudioInterface,
|
||||
public webrtc::AudioDeviceDataObserver,
|
||||
public webrtc::PeerConnectionObserver,
|
||||
public webrtc::CreateSessionDescriptionObserver,
|
||||
public webrtc::SetRemoteDescriptionObserverInterface,
|
||||
public webrtc::SetLocalDescriptionObserverInterface
|
||||
|
||||
{
|
||||
public:
|
||||
LLWebRTCImpl() :
|
||||
mTuningEnergy(0.0)
|
||||
{
|
||||
}
|
||||
~LLWebRTCImpl() {}
|
||||
|
||||
void init();
|
||||
|
||||
//
|
||||
// LLWebRTCDeviceInterface
|
||||
//
|
||||
|
||||
void refreshDevices() override;
|
||||
|
||||
void setDevicesObserver(LLWebRTCDevicesObserver *observer) override;
|
||||
void unsetDevicesObserver(LLWebRTCDevicesObserver *observer) override;
|
||||
void setCaptureDevice(const std::string& id) override;
|
||||
|
||||
void setRenderDevice(const std::string& id) override;
|
||||
|
||||
void setTuningMode(bool enable) override;
|
||||
double getTuningMicrophoneEnergy() override;
|
||||
|
||||
|
||||
void OnCaptureData(const void *audio_samples,
|
||||
const size_t num_samples,
|
||||
const size_t bytes_per_sample,
|
||||
const size_t num_channels,
|
||||
const uint32_t samples_per_sec) override;
|
||||
|
||||
void OnRenderData(const void *audio_samples,
|
||||
const size_t num_samples,
|
||||
const size_t bytes_per_sample,
|
||||
const size_t num_channels,
|
||||
const uint32_t samples_per_sec) override;
|
||||
|
||||
//
|
||||
// LLWebRTCSignalInterface
|
||||
//
|
||||
|
||||
void setSignalingObserver(LLWebRTCSignalingObserver *observer) override;
|
||||
void unsetSignalingObserver(LLWebRTCSignalingObserver *observer) override;
|
||||
bool initializeConnection() override;
|
||||
void shutdownConnection() override;
|
||||
void AnswerAvailable(const std::string &sdp) override;
|
||||
|
||||
|
||||
//
|
||||
// LLWebRTCAudioInterface
|
||||
//
|
||||
void setMute(bool mute) override;
|
||||
|
||||
//
|
||||
// PeerConnectionObserver implementation.
|
||||
//
|
||||
|
||||
void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) override {}
|
||||
void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
|
||||
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> &streams) override;
|
||||
void OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) override;
|
||||
void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> channel) override {}
|
||||
void OnRenegotiationNeeded() override {}
|
||||
void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override {};
|
||||
void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override;
|
||||
void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) override;
|
||||
void OnIceConnectionReceivingChange(bool receiving) override {}
|
||||
void OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) override;
|
||||
|
||||
//
|
||||
// CreateSessionDescriptionObserver implementation.
|
||||
//
|
||||
void OnSuccess(webrtc::SessionDescriptionInterface *desc) override;
|
||||
void OnFailure(webrtc::RTCError error) override;
|
||||
|
||||
//
|
||||
// SetRemoteDescriptionObserverInterface implementation.
|
||||
//
|
||||
void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override;
|
||||
|
||||
//
|
||||
// SetLocalDescriptionObserverInterface implementation.
|
||||
//
|
||||
void OnSetLocalDescriptionComplete(webrtc::RTCError error) override;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<rtc::Thread> mNetworkThread;
|
||||
std::unique_ptr<rtc::Thread> mWorkerThread;
|
||||
std::unique_ptr<rtc::Thread> mSignalingThread;
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> mPeerConnectionFactory;
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration mConfiguration;
|
||||
std::unique_ptr<webrtc::TaskQueueFactory> mTaskQueueFactory;
|
||||
|
||||
|
||||
// Devices
|
||||
void updateDevices();
|
||||
rtc::scoped_refptr<webrtc::AudioDeviceModule> mDeviceModule;
|
||||
std::vector<LLWebRTCDevicesObserver *> mVoiceDevicesObserverList;
|
||||
|
||||
double mTuningEnergy;
|
||||
|
||||
// signaling
|
||||
std::vector<LLWebRTCSignalingObserver *> mSignalingObserverList;
|
||||
std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> mCachedIceCandidates;
|
||||
bool mAnswerReceived;
|
||||
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> mPeerConnection;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LLWEBRTC_IMPL_H
|
||||
|
|
@ -30,6 +30,7 @@ include(LLKDU)
|
|||
include(LLPhysicsExtensions)
|
||||
include(LLPrimitive)
|
||||
include(LLWindow)
|
||||
include(LLWebRTC)
|
||||
include(NDOF)
|
||||
include(NVAPI)
|
||||
include(OPENAL)
|
||||
|
|
@ -689,6 +690,7 @@ set(viewer_SOURCE_FILES
|
|||
llvoiceclient.cpp
|
||||
llvoicevisualizer.cpp
|
||||
llvoicevivox.cpp
|
||||
llvoicewebrtc.cpp
|
||||
llvoinventorylistener.cpp
|
||||
llvopartgroup.cpp
|
||||
llvosky.cpp
|
||||
|
|
@ -1333,6 +1335,7 @@ set(viewer_HEADER_FILES
|
|||
llvoiceclient.h
|
||||
llvoicevisualizer.h
|
||||
llvoicevivox.h
|
||||
llvoicewebrtc.h
|
||||
llvoinventorylistener.h
|
||||
llvopartgroup.h
|
||||
llvosky.h
|
||||
|
|
@ -1433,6 +1436,7 @@ if (LINUX)
|
|||
endif (LINUX)
|
||||
|
||||
if (WINDOWS)
|
||||
|
||||
list(APPEND viewer_SOURCE_FILES
|
||||
llappviewerwin32.cpp
|
||||
llwindebug.cpp
|
||||
|
|
@ -1724,6 +1728,7 @@ if (WINDOWS)
|
|||
${SHARED_LIB_STAGING_DIR}/openjp2.dll
|
||||
${SHARED_LIB_STAGING_DIR}/libhunspell.dll
|
||||
${SHARED_LIB_STAGING_DIR}/uriparser.dll
|
||||
${CMAKE_BINARY_DIR}/llwebrtc/Release/llwebrtc.dll
|
||||
#${SHARED_LIB_STAGING_DIR}/${LL_INTDIR}/SLVoice.exe
|
||||
#${SHARED_LIB_STAGING_DIR}/${LL_INTDIR}/libsndfile-1.dll
|
||||
#${SHARED_LIB_STAGING_DIR}/${LL_INTDIR}/vivoxoal.dll
|
||||
|
|
@ -1920,6 +1925,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
llcorehttp
|
||||
llcommon
|
||||
llmeshoptimizer
|
||||
llwebrtc
|
||||
ll::ndof
|
||||
lllogin
|
||||
llprimitive
|
||||
|
|
|
|||
|
|
@ -15128,7 +15128,7 @@
|
|||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>vivox</string>
|
||||
<string>webrtc</string>
|
||||
</map>
|
||||
<key>WLSkyDetail</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -480,11 +480,11 @@ void audio_update_volume(bool force_update)
|
|||
|
||||
if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
|
||||
{
|
||||
voice_inst->setMuteMic(true);
|
||||
//voice_inst->setMuteMic(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
voice_inst->setMuteMic(false);
|
||||
//voice_inst->setMuteMic(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3136,6 +3136,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
capabilityNames.append("ParcelVoiceInfoRequest");
|
||||
capabilityNames.append("ProductInfoRequest");
|
||||
capabilityNames.append("ProvisionVoiceAccountRequest");
|
||||
capabilityNames.append("VoiceSignalingRequest");
|
||||
capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite
|
||||
capabilityNames.append("RegionObjects");
|
||||
capabilityNames.append("RemoteParcelRequest");
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llvoiceclient.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llvoicevivox.h"
|
||||
#include "llvoicewebrtc.h"
|
||||
#include "llviewernetwork.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "lldir.h"
|
||||
#include "llhttpnode.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llsdserialize.h"
|
||||
|
|
@ -161,6 +161,10 @@ void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &age
|
|||
{
|
||||
mVoiceModule = (LLVoiceModuleInterface *)LLVivoxVoiceClient::getInstance();
|
||||
}
|
||||
if (voice_server == "webrtc")
|
||||
{
|
||||
mVoiceModule = (LLVoiceModuleInterface *) LLWebRTCVoiceClient::getInstance();
|
||||
}
|
||||
else
|
||||
{
|
||||
mVoiceModule = NULL;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class LLVOAvatar;
|
|||
#include "lliosocket.h"
|
||||
#include "v3math.h"
|
||||
#include "llframetimer.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llcallingcard.h" // for LLFriendObserver
|
||||
#include "llsecapi.h"
|
||||
#include "llcontrol.h"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1 +1 @@
|
|||
e3bd0529a647d938ab6d48f26d21dd52c07ebc6e
|
||||
dd15c52581b3fe99e072b26872deba2560893fc4
|
||||
|
|
|
|||
Loading…
Reference in New Issue