# Conflicts:
#	autobuild.xml
#	indra/cmake/00-Common.cmake
#	indra/newview/app_settings/settings.xml
#	indra/newview/llagent.cpp
#	indra/newview/llgroupactions.cpp
#	indra/newview/llimview.cpp
#	indra/newview/llpanelpeople.h
#	indra/newview/llvoavatar.cpp
#	indra/newview/llvoavatar.h
#	indra/newview/llvoiceclient.cpp
#	indra/newview/llvoiceclient.h
#	indra/newview/llvoicevivox.cpp
#	indra/newview/llvoicevivox.h
#	indra/newview/viewer_manifest.py
#	scripts/messages/message_template.msg.sha1
master
Ansariel 2024-03-19 17:09:42 +01:00
commit 5e75273b49
49 changed files with 8238 additions and 2769 deletions

View File

@ -76,3 +76,6 @@ c/cpp:
- '**/*.i'
- '**/*.inl'
- '**/*.y'
'team:viewer':
- '*'

File diff suppressed because it is too large Load Diff

View File

@ -523,6 +523,13 @@
<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>
@ -705,6 +712,9 @@
<key>ProvisionVoiceAccountRequest</key>
<boolean>false</boolean>
<key>VoiceSignalingRequest</key>
<boolean>false</boolean>
<key>RemoteParcelRequest</key>
<boolean>false</boolean>

View File

@ -112,6 +112,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)

View File

@ -66,6 +66,7 @@ set(cmake_SOURCE_FILES
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
LibVLCPlugin.cmake
WebRTC.cmake
XmlRpcEpi.cmake
xxHash.cmake
ZLIBNG.cmake

32
indra/cmake/WebRTC.cmake Normal file
View File

@ -0,0 +1,32 @@
# -*- cmake -*-
include(Linking)
include(Prebuilt)
include_guard()
add_library( ll::webrtc INTERFACE IMPORTED )
target_include_directories( ll::webrtc SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include/webrtc" "${LIBS_PREBUILT_DIR}/include/webrtc/third_party/abseil-cpp")
use_prebuilt_binary(webrtc)
if (WINDOWS)
target_link_libraries( ll::webrtc INTERFACE webrtc.lib )
elseif (DARWIN)
FIND_LIBRARY(COREAUDIO_LIBRARY CoreAudio)
FIND_LIBRARY(COREGRAPHICS_LIBRARY CoreGraphics)
FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY AudioToolbox)
FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation)
FIND_LIBRARY(COCOA_LIBRARY Cocoa)
target_link_libraries( ll::webrtc INTERFACE
libwebrtc.a
${COREAUDIO_LIBRARY}
${AUDIOTOOLBOX_LIBRARY}
${COREGRAPHICS_LIBRARY}
${COREFOUNDATION_LIBRARY}
${COCOA_LIBRARY}
)
elseif (LINUX)
target_link_libraries( ll::webrtc INTERFACE libwebrtc )
endif (WINDOWS)

View File

@ -132,6 +132,7 @@ public:
friend LLQuaternion operator~(const LLQuaternion &a); // Returns a* (Conjugate of a)
bool operator==(const LLQuaternion &b) const; // Returns a == b
bool operator!=(const LLQuaternion &b) const; // Returns a != b
F64 operator[](int idx) const { return mQ[idx]; }
friend const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b); // Returns a * b

View File

@ -0,0 +1,60 @@
# -*- cmake -*-
# some webrtc headers require C++ 20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(00-Common)
include(Linking)
include(WebRTC)
project(llwebrtc)
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)
if (WINDOWS)
target_link_libraries(llwebrtc PRIVATE ll::webrtc
secur32
winmm
dmoguids
wmcodecdspuuid
msdmo
strmiids
iphlpapi)
elseif (DARWIN)
target_link_libraries(llwebrtc PRIVATE ll::webrtc)
elseif (LINUX)
target_link_libraries(llwebrtc PRIVATE ll::webrtc)
endif (WINDOWS)
target_include_directories( llwebrtc INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
if (WINDOWS)
set_property(TARGET llwebrtc PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreadedDebug")
endif (WINDOWS)
ADD_CUSTOM_COMMAND(TARGET llwebrtc POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:llwebrtc>
${SHARED_LIB_STAGING_DIR})
# Add tests
if (LL_TESTS)
endif (LL_TESTS)

1214
indra/llwebrtc/llwebrtc.cpp Normal file

File diff suppressed because it is too large Load Diff

233
indra/llwebrtc/llwebrtc.h Normal file
View File

@ -0,0 +1,233 @@
/**
* @file llwebrtc.h
* @brief WebRTC interface
*
* $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 tSoftware
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
/*
* llwebrtc wraps the native webrtc c++ library in a dynamic library with a simlified interface
* so that the viewer can use it. This is done because native webrtc has a different
* overall threading model than the viewer.
* The native webrtc library is also compiled with clang, and has memory management
* functions that conflict namespace-wise with those in the viewer.
*
* Due to these differences, code from the viewer cannot be pulled in to this
* dynamic library, so it remains very simple.
*/
#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
{
// LLWebRTCVoiceDevice is a simple representation of the
// components of a device, used to communicate this
// information to the viewer.
// A note on threading.
// Native WebRTC has it's own threading model. Some discussion
// can be found here (https://webrtc.github.io/webrtc-org/native-code/native-apis/)
//
// Note that all callbacks to observers will occurr on one of the WebRTC native threads
// (signaling, worker, etc.) Care should be taken to assure there are not
// bad interactions with the viewer threads.
class LLWebRTCVoiceDevice
{
public:
std::string mDisplayName; // friendly name for user interface purposes
std::string mID; // internal value for selection
LLWebRTCVoiceDevice(const std::string &display_name, const std::string &id) :
mDisplayName(display_name),
mID(id)
{};
};
typedef std::vector<LLWebRTCVoiceDevice> LLWebRTCVoiceDeviceList;
// The LLWebRTCDeviceObserver should be implemented by the viewer
// webrtc module, which will receive notifications when devices
// change (are unplugged, etc.)
class LLWebRTCDevicesObserver
{
public:
virtual void OnDevicesChanged(const LLWebRTCVoiceDeviceList &render_devices,
const LLWebRTCVoiceDeviceList &capture_devices) = 0;
};
// The LLWebRTCDeviceInterface provides a way for the viewer
// to enumerate, set, and get notifications of changes
// for both capture (microphone) and render (speaker)
// devices.
class LLWebRTCDeviceInterface
{
public:
// instructs webrtc to refresh the device list.
virtual void refreshDevices() = 0;
// set the capture and render devices using the unique identifier for the device
virtual void setCaptureDevice(const std::string& id) = 0;
virtual void setRenderDevice(const std::string& id) = 0;
// Device observers for device change callbacks.
virtual void setDevicesObserver(LLWebRTCDevicesObserver *observer) = 0;
virtual void unsetDevicesObserver(LLWebRTCDevicesObserver *observer) = 0;
// tuning and audio levels
virtual void setTuningMode(bool enable) = 0;
virtual float getTuningAudioLevel() = 0; // for use during tuning
virtual float getPeerConnectionAudioLevel() = 0; // for use when not tuning
};
// LLWebRTCAudioInterface provides the viewer with a way
// to set audio characteristics (mute, send and receive volume)
class LLWebRTCAudioInterface
{
public:
virtual void setMute(bool mute) = 0;
virtual void setReceiveVolume(float volume) = 0; // volume between 0.0 and 1.0
virtual void setSendVolume(float volume) = 0; // volume between 0.0 and 1.0
};
// LLWebRTCDataObserver allows the viewer voice module to be notified when
// data is received over the data channel.
class LLWebRTCDataObserver
{
public:
virtual void OnDataReceived(const std::string& data, bool binary) = 0;
};
// LLWebRTCDataInterface allows the viewer to send data over the data channel.
class LLWebRTCDataInterface
{
public:
virtual void sendData(const std::string& data, bool binary=false) = 0;
virtual void setDataObserver(LLWebRTCDataObserver *observer) = 0;
virtual void unsetDataObserver(LLWebRTCDataObserver *observer) = 0;
};
// LLWebRTCIceCandidate is a basic structure containing
// information needed for ICE trickling.
struct LLWebRTCIceCandidate
{
std::string mCandidate;
std::string mSdpMid;
int mMLineIndex;
};
// LLWebRTCSignalingObserver provides a way for the native
// webrtc library to notify the viewer voice module of
// various state changes.
class LLWebRTCSignalingObserver
{
public:
typedef enum e_ice_gathering_state {
ICE_GATHERING_NEW,
ICE_GATHERING_GATHERING,
ICE_GATHERING_COMPLETE
} EIceGatheringState;
// Called when ICE gathering states have changed.
// This may be called at any time, as ICE gathering
// can be redone while a connection is up.
virtual void OnIceGatheringState(EIceGatheringState state) = 0;
// Called when a new ice candidate is available.
virtual void OnIceCandidate(const LLWebRTCIceCandidate& candidate) = 0;
// Called when an offer is available after a connection is requested.
virtual void OnOfferAvailable(const std::string& sdp) = 0;
// Called when a connection enters a failure state and renegotiation is needed.
virtual void OnRenegotiationNeeded() = 0;
// Called when the audio channel has been established and audio
// can begin.
virtual void OnAudioEstablished(LLWebRTCAudioInterface *audio_interface) = 0;
// Called when the data channel has been established and data
// transfer can begin.
virtual void OnDataChannelReady(LLWebRTCDataInterface *data_interface) = 0;
// Called when a peer connection has finished shutting down.
virtual void OnPeerConnectionShutdown() = 0;
};
// LLWebRTCPeerConnectionInterface representsd a connection to a peer,
// in most cases a Secondlife WebRTC server. This interface
// allows for management of this peer connection.
class LLWebRTCPeerConnectionInterface
{
public:
virtual void setSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
virtual void unsetSignalingObserver(LLWebRTCSignalingObserver* observer) = 0;
virtual bool initializeConnection() = 0;
virtual bool shutdownConnection() = 0;
virtual void AnswerAvailable(const std::string &sdp) = 0;
};
// The following define the dynamic linked library
// exports.
// This library must be initialized before use.
LLSYMEXPORT void init();
// And should be terminated as part of shutdown.
LLSYMEXPORT void terminate();
// Return an interface for device management.
LLSYMEXPORT LLWebRTCDeviceInterface* getDeviceInterface();
// Allocate and free peer connections.
LLSYMEXPORT LLWebRTCPeerConnectionInterface* newPeerConnection();
LLSYMEXPORT void freePeerConnection(LLWebRTCPeerConnectionInterface *connection);
}
#endif // LLWEBRTC_H

View File

@ -0,0 +1,368 @@
/**
* @file llwebrtc_impl.h
* @brief WebRTC dynamic library implementation header
*
* $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
#if defined(_WIN32) || defined(_WIN64)
#define WEBRTC_WIN 1
#elif defined(__APPLE__)
#define WEBRTC_MAC 1
#define WEBRTC_POSIX 1
#elif __linux__
#define WEBRTC_LINUX 1
#endif
#include "llwebrtc.h"
// WebRTC Includes
#ifdef WEBRTC_WIN
#pragma warning(disable : 4996) // ignore 'deprecated.' We don't use the functions marked
// deprecated in the webrtc headers, but msvc complains anyway.
// Clang doesn't, and that's generally what webrtc uses.
#pragma warning(disable : 4068) // ignore 'invalid pragma.' There are clang pragma's in
// the webrtc headers, which msvc doesn't recognize.
#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 LLWebRTCPeerConnectionImpl;
// Implements a class allowing capture of audio data
// to determine audio level of the microphone.
class LLAudioDeviceObserver : public webrtc::AudioDeviceDataObserver
{
public:
LLAudioDeviceObserver();
// Retrieve the RMS audio loudness
float getMicrophoneEnergy();
// Data retrieved from the caputure device is
// passed in here for processing.
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;
// This is for data destined for the render device.
// not currently used.
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;
protected:
static const int NUM_PACKETS_TO_FILTER = 30; // 300 ms of smoothing (30 frames)
float mSumVector[NUM_PACKETS_TO_FILTER];
float mMicrophoneEnergy;
};
// Used to process/retrieve audio levels after
// all of the processing (AGC, AEC, etc.) for display in-world to the user.
class LLCustomProcessor : public webrtc::CustomProcessing
{
public:
LLCustomProcessor();
~LLCustomProcessor() override {}
// (Re-) Initializes the submodule.
void Initialize(int sample_rate_hz, int num_channels) override;
// Analyzes the given capture or render signal.
void Process(webrtc::AudioBuffer *audio) override;
// Returns a string representation of the module state.
std::string ToString() const override { return ""; }
float getMicrophoneEnergy() { return mMicrophoneEnergy; }
protected:
static const int NUM_PACKETS_TO_FILTER = 30; // 300 ms of smoothing
int mSampleRateHz;
int mNumChannels;
float mSumVector[NUM_PACKETS_TO_FILTER];
float mMicrophoneEnergy;
};
// Primary singleton implementation for interfacing
// with the native webrtc library.
class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceSink
{
public:
LLWebRTCImpl();
~LLWebRTCImpl() {}
void init();
void terminate();
//
// 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;
float getTuningAudioLevel() override;
float getPeerConnectionAudioLevel() override;
//
// AudioDeviceSink
//
void OnDevicesUpdated() override;
//
// Helpers
//
// The following thread helpers allow the
// LLWebRTCPeerConnectionImpl class to post
// tasks to the native webrtc threads.
void PostWorkerTask(absl::AnyInvocable<void() &&> task,
const webrtc::Location& location = webrtc::Location::Current())
{
mWorkerThread->PostTask(std::move(task), location);
}
void PostSignalingTask(absl::AnyInvocable<void() &&> task,
const webrtc::Location& location = webrtc::Location::Current())
{
mSignalingThread->PostTask(std::move(task), location);
}
void PostNetworkTask(absl::AnyInvocable<void() &&> task,
const webrtc::Location& location = webrtc::Location::Current())
{
mNetworkThread->PostTask(std::move(task), location);
}
void WorkerBlockingCall(rtc::FunctionView<void()> functor,
const webrtc::Location& location = webrtc::Location::Current())
{
mWorkerThread->BlockingCall(std::move(functor), location);
}
void SignalingBlockingCall(rtc::FunctionView<void()> functor,
const webrtc::Location& location = webrtc::Location::Current())
{
mSignalingThread->BlockingCall(std::move(functor), location);
}
void NetworkBlockingCall(rtc::FunctionView<void()> functor,
const webrtc::Location& location = webrtc::Location::Current())
{
mNetworkThread->BlockingCall(std::move(functor), location);
}
// Allows the LLWebRTCPeerConnectionImpl class to retrieve the
// native webrtc PeerConnectionFactory.
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> getPeerConnectionFactory()
{
return mPeerConnectionFactory;
}
// create or destroy a peer connection.
LLWebRTCPeerConnectionInterface* newPeerConnection();
void freePeerConnection(LLWebRTCPeerConnectionInterface* peer_connection);
// enables/disables capture via the capture device
void setRecording(bool recording);
protected:
// The native webrtc threads
std::unique_ptr<rtc::Thread> mNetworkThread;
std::unique_ptr<rtc::Thread> mWorkerThread;
std::unique_ptr<rtc::Thread> mSignalingThread;
// The factory that allows creation of native webrtc PeerConnections.
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> mPeerConnectionFactory;
// more native webrtc stuff
std::unique_ptr<webrtc::TaskQueueFactory> mTaskQueueFactory;
// Devices
void updateDevices();
rtc::scoped_refptr<webrtc::AudioDeviceModule> mTuningDeviceModule;
rtc::scoped_refptr<webrtc::AudioDeviceModule> mPeerDeviceModule;
std::vector<LLWebRTCDevicesObserver *> mVoiceDevicesObserverList;
// accessors in native webrtc for devices aren't apparently implemented yet.
bool mTuningMode;
int32_t mPlayoutDevice;
int32_t mRecordingDevice;
bool mMute;
LLAudioDeviceObserver * mTuningAudioDeviceObserver;
LLCustomProcessor * mPeerCustomProcessor;
// peer connections
std::vector<rtc::scoped_refptr<LLWebRTCPeerConnectionImpl>> mPeerConnections;
};
// The implementation of a peer connection, which contains
// the various interfaces used by the viewer to interact with
// the webrtc connection.
class LLWebRTCPeerConnectionImpl : public LLWebRTCPeerConnectionInterface,
public LLWebRTCAudioInterface,
public LLWebRTCDataInterface,
public webrtc::PeerConnectionObserver,
public webrtc::CreateSessionDescriptionObserver,
public webrtc::SetRemoteDescriptionObserverInterface,
public webrtc::SetLocalDescriptionObserverInterface,
public webrtc::DataChannelObserver
{
public:
LLWebRTCPeerConnectionImpl();
~LLWebRTCPeerConnectionImpl() {}
void init(LLWebRTCImpl * webrtc_impl);
void terminate();
virtual void AddRef() const override = 0;
virtual rtc::RefCountReleaseStatus Release() const override = 0;
//
// LLWebRTCPeerConnection
//
void setSignalingObserver(LLWebRTCSignalingObserver *observer) override;
void unsetSignalingObserver(LLWebRTCSignalingObserver *observer) override;
bool initializeConnection() override;
bool shutdownConnection() override;
void AnswerAvailable(const std::string &sdp) override;
//
// LLWebRTCAudioInterface
//
void setMute(bool mute) override;
void setReceiveVolume(float volume) override; // volume between 0.0 and 1.0
void setSendVolume(float volume) override; // volume between 0.0 and 1.0
//
// LLWebRTCDataInterface
//
void sendData(const std::string& data, bool binary=false) override;
void setDataObserver(LLWebRTCDataObserver *observer) override;
void unsetDataObserver(LLWebRTCDataObserver *observer) 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;
//
// DataChannelObserver implementation.
//
void OnStateChange() override;
void OnMessage(const webrtc::DataBuffer& buffer) override;
// Helpers
void resetMute();
void enableSenderTracks(bool enable);
void enableReceiverTracks(bool enable);
protected:
LLWebRTCImpl * mWebRTCImpl;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> mPeerConnectionFactory;
bool mMute;
// signaling
std::vector<LLWebRTCSignalingObserver *> mSignalingObserverList;
std::vector<std::unique_ptr<webrtc::IceCandidateInterface>> mCachedIceCandidates;
bool mAnswerReceived;
rtc::scoped_refptr<webrtc::PeerConnectionInterface> mPeerConnection;
rtc::scoped_refptr<webrtc::MediaStreamInterface> mLocalStream;
// data
std::vector<LLWebRTCDataObserver *> mDataObserverList;
rtc::scoped_refptr<webrtc::DataChannelInterface> mDataChannel;
};
}
#endif // LLWEBRTC_IMPL_H

View File

@ -806,6 +806,7 @@ set(viewer_SOURCE_FILES
llvoiceclient.cpp
llvoicevisualizer.cpp
llvoicevivox.cpp
llvoicewebrtc.cpp
llvoinventorylistener.cpp
llvopartgroup.cpp
llvosky.cpp
@ -1592,6 +1593,7 @@ set(viewer_HEADER_FILES
llvoiceclient.h
llvoicevisualizer.h
llvoicevivox.h
llvoicewebrtc.h
llvoinventorylistener.h
llvopartgroup.h
llvosky.h
@ -1813,6 +1815,7 @@ if (LINUX)
endif (LINUX)
if (WINDOWS)
list(APPEND viewer_SOURCE_FILES
growlmanager.cpp
growlnotifierwin.cpp
@ -2192,6 +2195,7 @@ if (WINDOWS)
#${SHARED_LIB_STAGING_DIR}/openjp2.dll # <FS:Ansariel> Only copy OpenJPEG dll if needed
${SHARED_LIB_STAGING_DIR}/libhunspell.dll
${SHARED_LIB_STAGING_DIR}/uriparser.dll
${SHARED_LIB_STAGING_DIR}/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
@ -2269,13 +2273,14 @@ if (WINDOWS)
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
stage_third_party_libs
llwebrtc
${COPY_INPUT_DEPENDENCIES}
COMMENT "Performing viewer_manifest copy"
)
add_custom_target(copy_w_viewer_manifest ALL DEPENDS ${CMAKE_CFG_INTDIR}/copy_touched.bat)
add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon copy_w_viewer_manifest)
add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon llwebrtc copy_w_viewer_manifest)
if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
@ -2404,6 +2409,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
llcorehttp
llcommon
llmeshoptimizer
llwebrtc
ll::ndof
lllogin
llprimitive

View File

@ -18837,7 +18837,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>vivox</string>
<string>webrtc</string>
</map>
<key>WLSkyDetail</key>
<map>

View File

@ -174,7 +174,7 @@ bool exoGroupMuteList::restoreDeferredGroupChat(const LLUUID& group)
gIMMgr->addSession(groupData.mName, IM_SESSION_INVITE, group);
uuid_vec_t ids;
LLIMModel::sendStartSession(group, group, ids, IM_SESSION_GROUP_START);
LLIMModel::sendStartSession(group, group, ids, IM_SESSION_GROUP_START, true);
if (!gAgent.isDoNotDisturb() && gSavedSettings.getU32("PlayModeUISndNewIncomingGroupIMSession") != 0)
{

View File

@ -753,7 +753,7 @@ void FSFloaterIM::onSysinfoButtonVisibilityChanged(const LLSD& yes)
}
// support sysinfo button -Zi
void FSFloaterIM::onChange(EStatusType status, const std::string &channelURI, bool proximal)
void FSFloaterIM::onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{

View File

@ -103,7 +103,7 @@ public:
//AO: Callbacks for voice handling formerly in llPanelImControlPanel
void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
void onChange(EStatusType status, const std::string &channelURI, bool proximal);
void onChange(EStatusType status, const LLSD& channelInfo, bool proximal);
void updateButtons(bool is_call_started);
void updateCallButton();
void changed(U32 mask);

View File

@ -339,7 +339,7 @@ bool LLAgent::isActionAllowed(const LLSD& sdname)
}
else
{
allow_agent_voice = channel->isActive() && channel->callStarted();
allow_agent_voice = channel->isActive();
}
}
@ -4877,10 +4877,6 @@ bool LLAgent::teleportCore(bool is_local)
}
make_ui_sound("UISndTeleportOut");
// MBW -- Let the voice client know a teleport has begun so it can leave the existing channel.
// This was breaking the case of teleporting within a single sim. Backing it out for now.
// LLVoiceClient::getInstance()->leaveChannel();
gObjectList.resetDerenderList();
return true;

View File

@ -3997,15 +3997,15 @@ LLSD LLAppViewer::getViewerInfo() const
{
LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion();
const std::string build_version = version.mBuildVersion;
std::ostringstream version_string;
if (std::equal(build_version.begin(), build_version.begin() + version.serverVersion.size(),
std::ostringstream version_string;
if (std::equal(version.mBuildVersion.begin(), version.mBuildVersion.begin() + version.serverVersion.size(),
version.serverVersion.begin()))
{ // Normal case: Show type and build version.
version_string << version.serverType << " " << build_version << std::endl;
version_string << version.voiceServerType << " " << version.mBuildVersion << std::endl;
}
else
{ // Mismatch: Show both versions.
version_string << version.serverVersion << "/" << build_version << std::endl;
version_string << version.voiceServerType << " " << version.serverVersion << "/" << version.mBuildVersion << std::endl;
}
info["VOICE_VERSION"] = version_string.str();
}
@ -5982,7 +5982,7 @@ void LLAppViewer::sendLogoutRequest()
if(LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->leaveChannel();
LLVoiceClient::getInstance()->setVoiceEnabled(false);
}
}
}

View File

@ -43,6 +43,7 @@
#ifndef LL_LLAPPVIEWER_H
#define LL_LLAPPVIEWER_H
#include "llapp.h"
#include "llallocator.h"
#include "llapr.h"
#include "llcontrol.h"

View File

@ -320,7 +320,7 @@ static void on_avatar_name_cache_start_call(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
std::string name = av_name.getDisplayName();
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true);
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, LLSD());
if (session_id != LLUUID::null)
{
gIMMgr->startCall(session_id);
@ -382,8 +382,7 @@ const LLUUID LLAvatarActions::startAdhocCall(const uuid_vec_t& ids, const LLUUID
// create the new ad hoc voice session
const std::string title = LLTrans::getString("conference-title");
LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START,
ids[0], id_array, true, floater_id);
LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, LLSD(), floater_id);
if (session_id == LLUUID::null)
{
// <FS:Ansariel> [FS Communication UI]
@ -446,7 +445,7 @@ const LLUUID LLAvatarActions::startConference(const uuid_vec_t& ids, const LLUUI
// id_array.push_back(*it);
}
const std::string title = LLTrans::getString("conference-title");
LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, false, floater_id);
LLUUID session_id = gIMMgr->addSession(title, IM_SESSION_CONFERENCE_START, ids[0], id_array, LLSD(), floater_id);
if (session_id == LLUUID::null)
{

View File

@ -108,7 +108,7 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)
// is created from the UICtrlFactory
// <FS:Ansariel> Add callback for user volume change
mVoiceLevelChangeCallbackConnection = LLVoiceClient::getInstance()->setUserVolumeUpdateCallback(boost::bind(&LLAvatarListItem::onUserVoiceLevelChange, this, _1));
mVoiceLevelChangeCallbackConnection = LLVoiceClient::setUserVolumeUpdateCallback(boost::bind(&LLAvatarListItem::onUserVoiceLevelChange, this, _1));
// </FS:Ansariel>
}

View File

@ -59,7 +59,7 @@ public:
: conversation(conv)
{}
virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal)
virtual void onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
conversation->showVoiceIndicator(conversation
&& status != STATUS_JOINING

View File

@ -610,7 +610,7 @@ void LLFloaterIMSession::onCallButtonClicked()
}
}
void LLFloaterIMSession::onChange(EStatusType status, const std::string &channelURI, bool proximal)
void LLFloaterIMSession::onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL)
{

View File

@ -116,8 +116,7 @@ public:
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
void onChange(EStatusType status, const std::string &channelURI,
bool proximal);
void onChange(EStatusType status, const LLSD& channelInfo, bool proximal);
virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
virtual void onVoiceChannelStateChanged(

View File

@ -294,7 +294,7 @@ void LLGroupActions::startCall(const LLUUID& group_id)
}
// [/RLVa:KB]
LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, true);
LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, LLSD());
if (session_id == LLUUID::null)
{
LL_WARNS() << "Error adding session" << LL_ENDL;

View File

@ -108,7 +108,23 @@ const S32 XL8_PADDING = 3; // XL8_START_TAG.size() + XL8_END_TAG.size()
/** Timeout of outgoing session initialization (in seconds) */
const static U32 SESSION_INITIALIZATION_TIMEOUT = 30;
void startConfrenceCoro(std::string url, LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId, LLSD agents);
// This enum corresponds to the sim's and adds P2P_CHAT_SESSION,
// as webrtc uses the multiagent chat mechanism for p2p calls,
// instead of relying on vivox calling.
// Don't change this without consulting a server developer.
enum EMultiAgentChatSessionType
{
GROUP_CHAT_SESSION = 0,
CONFERENCE_SESSION = 1,
P2P_CHAT_SESSION = 2,
SESSION_TYPE_COUNT
};
void startConferenceCoro(std::string url, LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId, LLSD agents);
void startP2PCoro(std::string url, LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId);
void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType);
void chatterBoxHistoryCoro(std::string url, LLUUID sessionId, std::string from, std::string message, U32 timestamp);
void start_deprecated_conference_chat(const LLUUID& temp_session_id, const LLUUID& creator_id, const LLUUID& other_participant_id, const LLSD& agents_to_invite);
@ -129,7 +145,7 @@ BOOL LLSessionTimeoutTimer::tick()
{
gIMMgr->showSessionStartError("session_initialization_timed_out_error", mSessionId);
}
return TRUE;
return TRUE;
}
@ -166,7 +182,7 @@ void process_dnd_im(const LLSD& notification)
name,
IM_NOTHING_SPECIAL,
fromID,
false,
LLSD(),
false); //will need slight refactor to retrieve whether offline message or not (assume online for now)
}
@ -531,7 +547,7 @@ void on_new_message(const LLSD& msg)
notify_of_message(msg, false);
}
void startConfrenceCoro(std::string url,
void startConferenceCoro(std::string url,
LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId, LLSD agents)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
@ -543,6 +559,9 @@ void startConfrenceCoro(std::string url,
postData["method"] = "start conference";
postData["session-id"] = tempSessionId;
postData["params"] = agents;
LLSD altParams;
altParams["voice_server_type"] = gSavedSettings.getString("VoiceServerType");
postData["alt_params"] = altParams;
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
@ -572,6 +591,38 @@ void startConfrenceCoro(std::string url,
}
}
void startP2PCoro(std::string url, LLUUID sessionID, LLUUID creatorId, LLUUID otherParticipantId)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("ConferenceChatStart", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLSD postData;
postData["method"] = "start p2p";
postData["session-id"] = sessionID;
postData["params"] = otherParticipantId;
LLSD altParams;
altParams["voice_server_type"] = gSavedSettings.getString("VoiceServerType");
postData["alt_params"] = altParams;
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status)
{
LL_WARNS("LLIMModel") << "Failed to start p2p session:" << postData << "->" << result << LL_ENDL;
// try an "old school" way.
// *TODO: What about other error status codes? 4xx 5xx?
if (status == LLCore::HttpStatus(HTTP_BAD_REQUEST))
{
static const std::string error_string("session_does_not_exist_error");
gIMMgr->showSessionStartError(error_string, sessionID);
}
}
}
void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
@ -784,7 +835,13 @@ LLIMModel::LLIMModel()
LLCallDialogManager::instance();
}
LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)
LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id,
const std::string& name,
const EInstantMessage& type,
const LLUUID& other_participant_id,
const uuid_vec_t& ids,
const LLSD& voiceChannelInfo,
bool has_offline_msg)
: mSessionID(session_id),
mName(name),
mType(type),
@ -803,36 +860,49 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
mCallBackEnabled(true),
mTextIMPossible(true),
mStartCallOnInitialize(false),
mStartedAsIMCall(voice),
mStartedAsIMCall(!voiceChannelInfo.isUndefined()),
mIsDNDsend(false),
mAvatarNameCacheConnection()
{
// set P2P type by default
mSessionType = P2P_SESSION;
mSessionType = P2P_SESSION;
bool p2pAsAdhocCall = false;
if (IM_NOTHING_SPECIAL == mType || IM_SESSION_P2P_INVITE == mType)
{
mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id);
{
LLVoiceP2POutgoingCallInterface *outgoingInterface =
LLVoiceClient::getInstance()->getOutgoingCallInterface(voiceChannelInfo);
if (outgoingInterface)
{
// only use LLVoiceChannelP2P if the provider can handle the special P2P interface,
// which uses the voice server to relay calls and invites. Otherwise,
// we use the group voice provider.
mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id, outgoingInterface);
}
else
{
p2pAsAdhocCall = true;
mVoiceChannel = new LLVoiceChannelGroup(session_id, name, true);
}
}
else
{
mVoiceChannel = new LLVoiceChannelGroup(session_id, name);
// determine whether it is group or conference session
if (gAgent.isInGroup(mSessionID))
{
mSessionType = GROUP_SESSION;
mVoiceChannel = new LLVoiceChannelGroup(session_id, name, false);
}
else
else
{
mSessionType = ADHOC_SESSION;
mVoiceChannel = new LLVoiceChannelGroup(session_id, name, false);
}
}
if(mVoiceChannel)
{
mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3));
}
mVoiceChannelStateChangeConnection = mVoiceChannel->setStateChangedCallback(boost::bind(&LLIMSession::onVoiceChannelStateChanged, this, _1, _2, _3));
mVoiceChannel->setChannelInfo(voiceChannelInfo);
mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
@ -844,8 +914,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
//we need to wait for session initialization for outgoing ad-hoc and group chat session
//correct session id for initiated ad-hoc chat will be received from the server
if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID,
mInitialTargetIDs, mType))
if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID, mInitialTargetIDs, mType, p2pAsAdhocCall))
{
//we don't need to wait for any responses
//so we're already initialized
@ -994,22 +1063,6 @@ LLIMModel::LLIMSession::~LLIMSession()
delete mSpeakers;
mSpeakers = NULL;
// End the text IM session if necessary
if(LLVoiceClient::getInstance() && mOtherParticipantID.notNull())
{
switch(mType)
{
case IM_NOTHING_SPECIAL:
case IM_SESSION_P2P_INVITE:
LLVoiceClient::getInstance()->endUserIMSession(mOtherParticipantID);
break;
default:
// Appease the linux compiler
break;
}
}
mVoiceChannelStateChangeConnection.disconnect();
// HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
@ -1618,7 +1671,7 @@ void LLIMModel::testMessages()
//session name should not be empty
bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)
const LLUUID& other_participant_id, const uuid_vec_t& ids, const LLSD& voiceChannelInfo, bool has_offline_msg)
{
if (name.empty())
{
@ -1632,7 +1685,7 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co
return false;
}
LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg);
LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids, voiceChannelInfo, has_offline_msg);
mId2SessionMap[session_id] = session;
// When notifying observer, name of session is used instead of "name", because they may not be the
@ -1644,11 +1697,11 @@ bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, co
}
bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, bool voice, bool has_offline_msg)
bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const LLSD& voiceChannelInfo, bool has_offline_msg)
{
uuid_vec_t ids;
ids.push_back(other_participant_id);
return newSession(session_id, name, type, other_participant_id, ids, voice, has_offline_msg);
return newSession(session_id, name, type, other_participant_id, ids, voiceChannelInfo, has_offline_msg);
}
bool LLIMModel::clearSession(const LLUUID& session_id)
@ -2315,7 +2368,8 @@ bool LLIMModel::sendStartSession(
const LLUUID& temp_session_id,
const LLUUID& other_participant_id,
const uuid_vec_t& ids,
EInstantMessage dialog)
EInstantMessage dialog,
bool p2p_as_adhoc_call)
{
if ( dialog == IM_SESSION_GROUP_START )
{
@ -2331,7 +2385,7 @@ bool LLIMModel::sendStartSession(
return true;
}
else if ( dialog == IM_SESSION_CONFERENCE_START )
else if (dialog == IM_SESSION_CONFERENCE_START )
{
LLSD agents;
for (int i = 0; i < (S32) ids.size(); i++)
@ -2346,8 +2400,8 @@ bool LLIMModel::sendStartSession(
std::string url = region->getCapability(
"ChatSessionRequest");
LLCoros::instance().launch("startConfrenceCoro",
boost::bind(&startConfrenceCoro, url,
LLCoros::instance().launch("startConferenceCoro",
boost::bind(&startConferenceCoro, url,
temp_session_id, gAgent.getID(), other_participant_id, agents));
}
else
@ -2362,7 +2416,16 @@ bool LLIMModel::sendStartSession(
//we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id)
return true;
}
else if ((dialog == IM_SESSION_P2P_INVITE) || (dialog == IM_NOTHING_SPECIAL))
{
LLViewerRegion *region = gAgent.getRegion();
if (region)
{
std::string url = region->getCapability("ChatSessionRequest");
LLCoros::instance().launch("startP2P", boost::bind(&startP2PCoro, url, temp_session_id, gAgent.getID(), other_participant_id));
}
return true;
}
return false;
}
@ -2609,6 +2672,12 @@ void LLCallDialogManager::onVoiceChannelStateChangedInt(const LLVoiceChannel::ES
}
break;
case LLVoiceChannel::STATE_NO_CHANNEL_INFO :
// This will happen in p2p calls using the adhoc
// infrastructure, which marks the channel as no channel info
// after the call is closed, which forces a dialogue.
return;
case LLVoiceChannel::STATE_HUNG_UP:
// this state is coming before session is changed
break;
@ -2951,15 +3020,15 @@ bool is_voice_call_type(const std::string &value)
}
LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
LLCallDialog(payload),
mAvatarNameCacheConnection()
LLCallDialog(payload),
mAvatarNameCacheConnection()
{
}
void LLIncomingCallDialog::onLifetimeExpired()
{
std::string session_handle = mPayload["session_handle"].asString();
if (LLVoiceClient::getInstance()->isValidChannel(session_handle))
LLVoiceP2PIncomingCallInterfacePtr call = LLVoiceClient::getInstance()->getIncomingCallInterface(mPayload["voice_session_info"]);
if (call)
{
// restart notification's timer if call is still valid
mLifetimeTimer.start();
@ -3139,6 +3208,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
LLUUID session_id = payload["session_id"].asUUID();
LLUUID caller_id = payload["caller_id"].asUUID();
std::string session_name = payload["session_name"].asString();
if (session_name.empty())
{
session_name = payload["caller_name"].asString();
}
EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
bool voice = true;
@ -3155,10 +3228,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
{
// create a normal IM session
session_id = gIMMgr->addP2PSession(
session_name,
caller_id,
payload["session_handle"].asString(),
payload["session_uri"].asString());
session_name, caller_id, payload["voice_channel_info"]);
if (voice)
{
@ -3208,7 +3278,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
}
}
gIMMgr->addSession(correct_session_name, type, session_id, true);
gIMMgr->addSession(correct_session_name, type, session_id, payload["voice_channel_info"]);
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
@ -3238,10 +3308,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
{
if (type == IM_SESSION_P2P_INVITE)
{
if(LLVoiceClient::getInstance())
LLVoiceP2PIncomingCallInterfacePtr call = LLVoiceClient::getInstance()->getIncomingCallInterface(payload["voice_session_info"]);
if (call)
{
std::string s = payload["session_handle"].asString();
LLVoiceClient::getInstance()->declineInvite(s);
call->declineInvite();
}
}
else
@ -3264,90 +3334,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
}
}
bool inviteUserResponse(const LLSD& notification, const LLSD& response)
{
if (!gIMMgr || gDisconnected)
return false;
const LLSD& payload = notification["payload"];
LLUUID session_id = payload["session_id"].asUUID();
EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch(option)
{
case 0: // accept
{
if (type == IM_SESSION_P2P_INVITE)
{
// create a normal IM session
session_id = gIMMgr->addP2PSession(
payload["session_name"].asString(),
payload["caller_id"].asUUID(),
payload["session_handle"].asString(),
payload["session_uri"].asString());
gIMMgr->startCall(session_id);
gIMMgr->clearPendingAgentListUpdates(session_id);
gIMMgr->clearPendingInvitation(session_id);
}
else
{
gIMMgr->addSession(
payload["session_name"].asString(),
type,
session_id, true);
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
LLCoros::instance().launch("chatterBoxInvitationCoro",
boost::bind(&chatterBoxInvitationCoro, url,
session_id, inv_type));
}
}
break;
case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
{
// mute the sender of this invite
if (!LLMuteList::getInstance()->isMuted(payload["caller_id"].asUUID()))
{
LLMute mute(payload["caller_id"].asUUID(), payload["caller_name"].asString(), LLMute::AGENT);
LLMuteList::getInstance()->add(mute);
}
}
/* FALLTHROUGH */
case 1: // decline
{
if (type == IM_SESSION_P2P_INVITE)
{
std::string s = payload["session_handle"].asString();
LLVoiceClient::getInstance()->declineInvite(s);
}
else
{
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
LLSD data;
data["method"] = "decline invitation";
data["session-id"] = session_id;
LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, data,
"Invitation declined.",
"Invitation decline failed.");
}
}
gIMMgr->clearPendingAgentListUpdates(session_id);
gIMMgr->clearPendingInvitation(session_id);
break;
}
return false;
}
//
// Member Functions
//
@ -3480,7 +3466,7 @@ void LLIMMgr::addMessage(
}
// </FS:Ansariel>
LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg);
LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, LLSD(), is_offline_msg);
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
if (session)
@ -3766,22 +3752,11 @@ void LLIMMgr::autoStartCallOnStartup(const LLUUID& session_id)
}
LLUUID LLIMMgr::addP2PSession(const std::string& name,
const LLUUID& other_participant_id,
const std::string& voice_session_handle,
const std::string& caller_uri)
const LLUUID& other_participant_id,
const LLSD& voice_channel_info)
{
LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id, true);
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
if (speaker_mgr)
{
LLVoiceChannelP2P* voice_channel = dynamic_cast<LLVoiceChannelP2P*>(speaker_mgr->getVoiceChannel());
if (voice_channel)
{
voice_channel->setSessionHandle(voice_session_handle, caller_uri);
}
}
return session_id;
LL_DEBUGS("Voice") << "Add p2p voice channel info: " << voice_channel_info << LL_ENDL;
return addSession(name, IM_NOTHING_SPECIAL, other_participant_id, voice_channel_info);
}
// This adds a session to the talk view. The name is the local name of
@ -3791,11 +3766,12 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
LLUUID LLIMMgr::addSession(
const std::string& name,
EInstantMessage dialog,
const LLUUID& other_participant_id, bool voice)
const LLUUID& other_participant_id,
const LLSD& voiceChannelInfo)
{
std::vector<LLUUID> ids;
ids.push_back(other_participant_id);
LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voice);
LLUUID session_id = addSession(name, dialog, other_participant_id, ids, voiceChannelInfo);
return session_id;
}
@ -3805,7 +3781,8 @@ LLUUID LLIMMgr::addSession(
const std::string& name,
EInstantMessage dialog,
const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids, bool voice,
const std::vector<LLUUID>& ids,
const LLSD& voiceChannelInfo,
const LLUUID& floater_id)
{
if (ids.empty())
@ -3841,7 +3818,9 @@ LLUUID LLIMMgr::addSession(
bool new_session = (LLIMModel::getInstance()->findIMSession(session_id) == NULL);
//works only for outgoing ad-hoc sessions
if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size())
if (new_session &&
((IM_NOTHING_SPECIAL == dialog) || (IM_SESSION_P2P_INVITE == dialog) || (IM_SESSION_CONFERENCE_START == dialog)) &&
ids.size())
{
LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids);
if (ad_hoc_found)
@ -3854,7 +3833,7 @@ LLUUID LLIMMgr::addSession(
//Notify observers that a session was added
if (new_session)
{
LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice);
LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voiceChannelInfo);
}
//Notifies observers that the session was already added
else
@ -3938,9 +3917,15 @@ void LLIMMgr::inviteToSession(
const std::string& caller_name,
EInstantMessage type,
EInvitationType inv_type,
const std::string& session_handle,
const std::string& session_uri)
const LLSD& voice_channel_info)
{
if (caller_id == gAgentID)
{
// ignore invites from ourself.
return;
}
std::string notify_box_type;
// voice invite question is different from default only for group call (EXT-7118)
std::string question_type = "VoiceInviteQuestionDefault";
@ -3981,11 +3966,12 @@ void LLIMMgr::inviteToSession(
payload["caller_name"] = caller_name;
payload["type"] = type;
payload["inv_type"] = inv_type;
payload["session_handle"] = session_handle;
payload["session_uri"] = session_uri;
payload["voice_channel_info"] = voice_channel_info;
payload["notify_box_type"] = notify_box_type;
payload["question_type"] = question_type;
LL_WARNS("Voice") << "INVITE PAYLOAD: " << payload << LL_ENDL;
//ignore invites from muted residents
if (!is_linden)
{
@ -4042,7 +4028,7 @@ void LLIMMgr::inviteToSession(
fixed_session_name = av_name.getDisplayName();
}
}
LLIMModel::getInstance()->newSession(session_id, fixed_session_name, IM_NOTHING_SPECIAL, caller_id, false, false);
LLIMModel::getInstance()->newSession(session_id, fixed_session_name, IM_NOTHING_SPECIAL, caller_id, LLSD(), false);
}
LLSD args;
@ -4125,7 +4111,7 @@ bool LLIMMgr::restoreSnoozedSession(const LLUUID& session_id)
gIMMgr->addSession(groupData.mName, IM_SESSION_INVITE, session_id);
uuid_vec_t ids;
LLIMModel::sendStartSession(session_id, session_id, ids, IM_SESSION_GROUP_START);
LLIMModel::sendStartSession(session_id, session_id, ids, IM_SESSION_GROUP_START, true);
if (!gAgent.isDoNotDisturb() && gSavedSettings.getU32("PlayModeUISndNewIncomingGroupIMSession") != 0)
{
@ -4312,7 +4298,6 @@ bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection dir
{
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
if (!voice_channel) return false;
voice_channel->setCallDirection(direction);
voice_channel->activate();
return true;
@ -4947,13 +4932,16 @@ public:
return;
}
BOOL session_type_p2p = input["body"]["voice"].get("invitation_type").asInteger() == EMultiAgentChatSessionType::P2P_CHAT_SESSION;
LL_DEBUGS("Voice") << "Received P2P voice information from the server: " << input["body"]<< LL_ENDL;
gIMMgr->inviteToSession(
input["body"]["session_id"].asUUID(),
input["body"]["session_name"].asString(),
input["body"]["from_id"].asUUID(),
input["body"]["from_name"].asString(),
IM_SESSION_INVITE,
LLIMMgr::INVITATION_TYPE_VOICE);
session_type_p2p ? IM_SESSION_P2P_INVITE : IM_SESSION_INVITE,
LLIMMgr::INVITATION_TYPE_VOICE,
input["body"]["voice"]);
}
else if ( input["body"].has("immediate") )
{

View File

@ -89,7 +89,7 @@ public:
// [/SL:KB]
LLIMSession(const LLUUID& session_id, const std::string& name,
const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg);
const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, const LLSD& voiceChannelInfo, bool has_offline_msg);
virtual ~LLIMSession();
void sessionInitReplyReceived(const LLUUID& new_session_id);
@ -224,10 +224,10 @@ public:
* @param name session name should not be empty, will return false if empty
*/
bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,
const uuid_vec_t& ids, bool voice = false, bool has_offline_msg = false);
const uuid_vec_t& ids, const LLSD& voiceChannelInfo = LLSD(), bool has_offline_msg = false);
bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
const LLUUID& other_participant_id, bool voice = false, bool has_offline_msg = false);
bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID &other_participant_id,
const LLSD &voiceChannelInfo = LLSD(), bool has_offline_msg = false);
/**
* Remove all session data associated with a session specified by session_id
@ -338,7 +338,7 @@ public:
static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
const uuid_vec_t& ids, EInstantMessage dialog);
const uuid_vec_t& ids, EInstantMessage dialog, bool p2p_as_adhoc_call);
static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing);
static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id,
const LLUUID& other_participant_id, EInstantMessage dialog);
@ -427,7 +427,8 @@ public:
// session.
LLUUID addSession(const std::string& name,
EInstantMessage dialog,
const LLUUID& other_participant_id, bool voice = false);
const LLUUID& other_participant_id,
const LLSD& voiceChannelInfo = LLSD());
// Adds a session using a specific group of starting agents
// the dialog type is assumed correct. Returns the uuid of the session.
@ -435,7 +436,8 @@ public:
LLUUID addSession(const std::string& name,
EInstantMessage dialog,
const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids, bool voice = false,
const std::vector<LLUUID> &ids,
const LLSD& voiceChannelInfo = LLSD(),
const LLUUID& floater_id = LLUUID::null);
/**
@ -445,10 +447,7 @@ public:
* @param caller_uri - sip URI of caller. It should be always be passed into the method to avoid
* incorrect working of LLVoiceChannel instances. See EXT-2985.
*/
LLUUID addP2PSession(const std::string& name,
const LLUUID& other_participant_id,
const std::string& voice_session_handle,
const std::string& caller_uri);
LLUUID addP2PSession(const std::string &name, const LLUUID &other_participant_id, const LLSD &voice_call_info);
/**
* Leave the session with session id. Send leave session notification
@ -463,9 +462,9 @@ public:
const LLUUID& caller,
const std::string& caller_name,
EInstantMessage type,
EInvitationType inv_type,
const std::string& session_handle = LLStringUtil::null,
const std::string& session_uri = LLStringUtil::null);
EInvitationType inv_type,
const LLSD &voice_channel_info = LLSD()
);
void processIMTypingStart(const LLUUID& from_id, const EInstantMessage im_type);
void processIMTypingStop(const LLUUID& from_id, const EInstantMessage im_type);

View File

@ -343,7 +343,7 @@ void LLPanelGroup::changed(LLGroupChange gc)
}
// virtual
void LLPanelGroup::onChange(EStatusType status, const std::string &channelURI, bool proximal)
void LLPanelGroup::onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{

View File

@ -62,7 +62,7 @@ public:
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
/*virtual*/ void onChange(EStatusType status, const LLSD& channelInfo, bool proximal);
void showNotice(const std::string& subject,
const std::string& message,

View File

@ -839,7 +839,7 @@ BOOL LLPanelPeople::postBuild()
}
// virtual
void LLPanelPeople::onChange(EStatusType status, const std::string &channelURI, bool proximal)
void LLPanelPeople::onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{

View File

@ -65,7 +65,7 @@ public:
/*virtual*/ bool notifyChildren(const LLSD& info);
// Implements LLVoiceClientStatusObserver::onChange() to enable call buttons
// when voice is available
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
/*virtual*/ void onChange(EStatusType status, const LLSD& channelInfo, bool proximal);
// <FS:Ansariel> CTRL-F focusses local search editor
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ bool hasAccelerators() const { return true; }

View File

@ -1811,7 +1811,7 @@ void LLPanelProfileSecondLife::changed(U32 mask)
}
// virtual, called by LLVoiceClient
void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal)
void LLPanelProfileSecondLife::onChange(EStatusType status, const LLSD& channelInfo, bool proximal)
{
if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL)
{

View File

@ -100,7 +100,7 @@ public:
// Implements LLVoiceClientStatusObserver::onChange() to enable the call
// button when voice is available
void onChange(EStatusType status, const std::string &channelURI, bool proximal) override;
void onChange(EStatusType status, const LLSD& channelInfo, bool proximal) override;
void setAvatarId(const LLUUID& avatar_id) override;

View File

@ -236,43 +236,46 @@ void LLPanelVoiceDeviceSettings::refresh()
if(mCtrlInputDevices)
{
mCtrlInputDevices->removeall();
mCtrlInputDevices->add(getLocalizedDeviceName(DEFAULT_DEVICE), DEFAULT_DEVICE, ADD_BOTTOM);
for(device=LLVoiceClient::getInstance()->getCaptureDevices().begin();
device != LLVoiceClient::getInstance()->getCaptureDevices().end();
device++)
LLVoiceDeviceList devices = LLVoiceClient::getInstance()->getCaptureDevices();
if (devices.size() > 0) // if zero, we've not received our devices yet
{
mCtrlInputDevices->add(getLocalizedDeviceName(device->display_name), device->full_name, ADD_BOTTOM);
}
mCtrlInputDevices->removeall();
mCtrlInputDevices->add(getLocalizedDeviceName(DEFAULT_DEVICE), DEFAULT_DEVICE, ADD_BOTTOM);
for (auto& device : devices)
{
mCtrlInputDevices->add(getLocalizedDeviceName(device.display_name), device.full_name, ADD_BOTTOM);
}
// Fix invalid input audio device preference.
if (!mCtrlInputDevices->setSelectedByValue(mInputDevice, TRUE))
{
mCtrlInputDevices->setValue(DEFAULT_DEVICE);
gSavedSettings.setString("VoiceInputAudioDevice", DEFAULT_DEVICE);
mInputDevice = DEFAULT_DEVICE;
// Fix invalid input audio device preference.
if (!mCtrlInputDevices->setSelectedByValue(mInputDevice, TRUE))
{
mCtrlInputDevices->setValue(DEFAULT_DEVICE);
gSavedSettings.setString("VoiceInputAudioDevice", DEFAULT_DEVICE);
mInputDevice = DEFAULT_DEVICE;
}
}
}
if(mCtrlOutputDevices)
{
mCtrlOutputDevices->removeall();
mCtrlOutputDevices->add(getLocalizedDeviceName(DEFAULT_DEVICE), DEFAULT_DEVICE, ADD_BOTTOM);
for(device = LLVoiceClient::getInstance()->getRenderDevices().begin();
device != LLVoiceClient::getInstance()->getRenderDevices().end();
device++)
LLVoiceDeviceList devices = LLVoiceClient::getInstance()->getRenderDevices();
if (devices.size() > 0) // if zero, we've not received our devices yet
{
mCtrlOutputDevices->add(getLocalizedDeviceName(device->display_name), device->full_name, ADD_BOTTOM);
}
mCtrlOutputDevices->removeall();
mCtrlOutputDevices->add(getLocalizedDeviceName(DEFAULT_DEVICE), DEFAULT_DEVICE, ADD_BOTTOM);
// Fix invalid output audio device preference.
if (!mCtrlOutputDevices->setSelectedByValue(mOutputDevice, TRUE))
{
mCtrlOutputDevices->setValue(DEFAULT_DEVICE);
gSavedSettings.setString("VoiceOutputAudioDevice", DEFAULT_DEVICE);
mOutputDevice = DEFAULT_DEVICE;
for (auto& device : devices)
{
mCtrlOutputDevices->add(getLocalizedDeviceName(device.display_name), device.full_name, ADD_BOTTOM);
}
// Fix invalid output audio device preference.
if (!mCtrlOutputDevices->setSelectedByValue(mOutputDevice, TRUE))
{
mCtrlOutputDevices->setValue(DEFAULT_DEVICE);
gSavedSettings.setString("VoiceOutputAudioDevice", DEFAULT_DEVICE);
mOutputDevice = DEFAULT_DEVICE;
}
}
}
}
@ -316,8 +319,11 @@ void LLPanelVoiceDeviceSettings::onCommitInputDevice()
if(LLVoiceClient::getInstance())
{
mInputDevice = mCtrlInputDevices->getValue().asString();
LLVoiceClient::getInstance()->setRenderDevice(mInputDevice);
LLVoiceClient::getInstance()->setCaptureDevice(mInputDevice);
}
// the preferences floater stuff is a mess, hence apply will never
// be called when 'ok' is pressed, so just force it for now.
apply();
}
void LLPanelVoiceDeviceSettings::onCommitOutputDevice()
@ -328,6 +334,9 @@ void LLPanelVoiceDeviceSettings::onCommitOutputDevice()
mOutputDevice = mCtrlOutputDevices->getValue().asString();
LLVoiceClient::getInstance()->setRenderDevice(mOutputDevice);
}
// the preferences floater stuff is a mess, hence apply will never
// be called when 'ok' is pressed, so just force it for now.
apply();
}
void LLPanelVoiceDeviceSettings::onOutputDevicesClicked()

View File

@ -4296,7 +4296,7 @@ LLSD transform_cert_args(LLPointer<LLCertificate> cert)
// are actually arrays, and we want to format them as comma separated
// strings, so special case those.
LLSDSerialize::toXML(cert_info[iter->first], std::cout);
if((iter->first == std::string(CERT_KEY_USAGE)) ||
if((iter->first== std::string(CERT_KEY_USAGE)) ||
(iter->first == std::string(CERT_EXTENDED_KEY_USAGE)))
{
value = "";

View File

@ -46,7 +46,7 @@ public:
// requests will be throttled from a non-trusted browser
LLHelpHandler() : LLCommandHandler("help", UNTRUSTED_CLICK_ONLY) {}
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) override
{
LLViewerHelp* vhelp = LLViewerHelp::getInstance();
if (! vhelp)

View File

@ -3392,6 +3392,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");

View File

@ -43,6 +43,7 @@
#include "m4math.h" // LLMatrix4
#include "llframetimer.h"
#include "llreflectionmap.h"
#include "llpointer.h"
// Surface id's
#define LAND 1
@ -578,7 +579,7 @@ public:
U8 mCentralBakeVersion;
LLVOCacheEntry* mLastVisitedEntry;
U32 mInvisibilityCheckHistory;
U32 mInvisibilityCheckHistory;
// Information for Homestead / CR-53
S32 mClassID;

View File

@ -633,7 +633,8 @@ BOOL LLVOAvatar::sShowAnimationDebug = FALSE;
BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
F32 LLVOAvatar::sLODFactor = 1.f;
F32 LLVOAvatar::sPhysicsLODFactor = 1.f;
BOOL LLVOAvatar::sJointDebug = FALSE;
BOOL LLVOAvatar::sJointDebug = FALSE;
BOOL LLVOAvatar::sLipSyncEnabled = FALSE;
F32 LLVOAvatar::sUnbakedTime = 0.f;
F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
F32 LLVOAvatar::sGreyTime = 0.f;
@ -1235,6 +1236,8 @@ void LLVOAvatar::initClass()
LLControlAvatar::sRegionChangedSlot = gAgent.addRegionChangedCallback(&LLControlAvatar::onRegionChanged);
sCloudTexture = LLViewerTextureManager::getFetchedTextureFromFile("cloud-particle.j2c");
gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVOAvatar::handleVOAvatarPrefsChanged, _2));
initCloud();
}
@ -1243,6 +1246,12 @@ void LLVOAvatar::cleanupClass()
{
}
bool LLVOAvatar::handleVOAvatarPrefsChanged(const LLSD &newvalue)
{
sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled");
return true;
}
LLPartSysData LLVOAvatar::sCloud;
void LLVOAvatar::initCloud()
{
@ -3273,7 +3282,7 @@ void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
if ( voice_enabled
&& mLastRezzedStatus > 0 // no point updating lip-sync for clouds
&& (LLVoiceClient::getInstance()->lipSyncEnabled())
&& sLipSyncEnabled
&& LLVoiceClient::getInstance()->getIsSpeaking( mID ) )
{
F32 ooh_morph_amount = 0.0f;

View File

@ -108,8 +108,10 @@ public:
static void cleanupClass(); // Cleanup data that's only init'd once per class.
static void initCloud();
virtual void initInstance(); // Called after construction to initialize the class.
protected:
virtual ~LLVOAvatar();
static bool handleVOAvatarPrefsChanged(const LLSD &newvalue);
/** Initialization
** **
@ -380,6 +382,8 @@ public:
static F32 sLODFactor; // user-settable LOD factor
static F32 sPhysicsLODFactor; // user-settable physics LOD factor
static BOOL sJointDebug; // output total number of joints being touched for each avatar
static BOOL sLipSyncEnabled;
static LLPartSysData sCloud;
static LLPointer<LLViewerTexture> sCloudTexture;

View File

@ -39,7 +39,6 @@
#include "llcorehttputil.h"
LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
LLVoiceChannel::channel_changed_signal_t LLVoiceChannel::sCurrentVoiceChannelChangedSignal;
@ -89,29 +88,18 @@ LLVoiceChannel::~LLVoiceChannel()
}
sVoiceChannelMap.erase(mSessionID);
sVoiceChannelURIMap.erase(mURI);
}
void LLVoiceChannel::setChannelInfo(
const std::string& uri,
const std::string& credentials)
void LLVoiceChannel::setChannelInfo(const LLSD &channelInfo)
{
setURI(uri);
mCredentials = credentials;
mChannelInfo = channelInfo;
if (mState == STATE_NO_CHANNEL_INFO)
{
if (mURI.empty())
if (mChannelInfo.isUndefined())
{
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
LL_WARNS("Voice") << "Received empty URI for channel " << mSessionName << LL_ENDL;
deactivate();
}
else if (mCredentials.empty())
{
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
LL_WARNS("Voice") << "Received empty credentials for channel " << mSessionName << LL_ENDL;
LL_WARNS("Voice") << "Received empty channel info for channel " << mSessionName << LL_ENDL;
deactivate();
}
else
@ -130,9 +118,15 @@ void LLVoiceChannel::setChannelInfo(
}
}
void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
void LLVoiceChannel::onChange(EStatusType type, const LLSD& channelInfo, bool proximal)
{
if (channelURI != mURI)
LL_DEBUGS("Voice") << "Incoming channel info: " << channelInfo << LL_ENDL;
LL_DEBUGS("Voice") << "Current channel info: " << mChannelInfo << LL_ENDL;
if (mChannelInfo.isUndefined())
{
mChannelInfo = channelInfo;
}
if (!LLVoiceClient::getInstance()->compareChannels(mChannelInfo, channelInfo))
{
return;
}
@ -153,7 +147,7 @@ void LLVoiceChannel::handleStatusChange(EStatusType type)
switch(type)
{
case STATUS_LOGIN_RETRY:
// no user notice
// no user notice
break;
case STATUS_LOGGED_IN:
break;
@ -193,7 +187,7 @@ void LLVoiceChannel::handleError(EStatusType type)
BOOL LLVoiceChannel::isActive()
{
// only considered active when currently bound channel matches what our channel
return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
return callStarted() && LLVoiceClient::getInstance()->isCurrentChannel(mChannelInfo);
}
BOOL LLVoiceChannel::callStarted()
@ -246,10 +240,8 @@ void LLVoiceChannel::activate()
// activating the proximal channel between IM calls
LLVoiceChannel* old_channel = sCurrentVoiceChannel;
sCurrentVoiceChannel = this;
mCallDialogPayload["old_channel_name"] = "";
if (old_channel)
{
mCallDialogPayload["old_channel_name"] = old_channel->getSessionName();
old_channel->deactivate();
}
}
@ -257,7 +249,7 @@ void LLVoiceChannel::activate()
if (mState == STATE_NO_CHANNEL_INFO)
{
// responsible for setting status to active
getChannelInfo();
requestChannelInfo();
}
else
{
@ -270,7 +262,7 @@ void LLVoiceChannel::activate()
sCurrentVoiceChannelChangedSignal(this->mSessionID);
}
void LLVoiceChannel::getChannelInfo()
void LLVoiceChannel::requestChannelInfo()
{
// pretend we have everything we need
if (sCurrentVoiceChannel == this)
@ -293,20 +285,6 @@ LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
}
}
//static
LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
{
voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
if (found_it == sVoiceChannelURIMap.end())
{
return NULL;
}
else
{
return found_it->second;
}
}
LLVoiceChannel* LLVoiceChannel::getCurrentVoiceChannel()
{
return sCurrentVoiceChannel;
@ -319,13 +297,6 @@ void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
}
void LLVoiceChannel::setURI(std::string uri)
{
sVoiceChannelURIMap.erase(mURI);
mURI = uri;
sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
}
void LLVoiceChannel::setState(EState state)
{
switch(state)
@ -410,8 +381,11 @@ boost::signals2::connection LLVoiceChannel::setCurrentVoiceChannelChangedCallbac
// LLVoiceChannelGroup
//
LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
LLVoiceChannel(session_id, session_name)
LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID &session_id,
const std::string &session_name,
bool is_p2p) :
LLVoiceChannel(session_id, session_name),
mIsP2P(is_p2p)
{
mRetries = DEFAULT_RETRIES_COUNT;
mIsRetrying = FALSE;
@ -424,7 +398,15 @@ void LLVoiceChannelGroup::deactivate()
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
}
LLVoiceChannel::deactivate();
}
if (mIsP2P)
{
// void the channel info for p2p adhoc channels
// so we request it again, hence throwing up the
// connect dialogue on the other side.
setState(STATE_NO_CHANNEL_INFO);
}
}
void LLVoiceChannelGroup::activate()
{
@ -435,65 +417,64 @@ void LLVoiceChannelGroup::activate()
if (callStarted())
{
// we have the channel info, just need to use it now
LLVoiceClient::getInstance()->setNonSpatialChannel(
mURI,
mCredentials);
LLVoiceClient::getInstance()->setNonSpatialChannel(mChannelInfo,
mIsP2P && (mCallDirection == OUTGOING_CALL),
mIsP2P);
if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
if (mIsP2P)
{
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionID);
// Adding ad-hoc call participants to Recent People List.
// If it's an outgoing ad-hoc, we can use mInitialTargetIDs that holds IDs of people we
// called(both online and offline) as source to get people for recent (STORM-210).
if (session->isOutgoingAdHoc())
LLIMModel::addSpeakersToRecent(mSessionID);
}
else
{
if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
{
for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();
it!=session->mInitialTargetIDs.end();++it)
LLIMModel::LLIMSession *session = LLIMModel::getInstance()->findIMSession(mSessionID);
// Adding ad-hoc call participants to Recent People List.
// If it's an outgoing ad-hoc, we can use mInitialTargetIDs that holds IDs of people we
// called(both online and offline) as source to get people for recent (STORM-210).
if (session->isOutgoingAdHoc())
{
const LLUUID id = *it;
LLRecentPeople::instance().add(id);
for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin(); it != session->mInitialTargetIDs.end(); ++it)
{
const LLUUID id = *it;
LLRecentPeople::instance().add(id);
}
}
// If this ad-hoc is incoming then trying to get ids of people from mInitialTargetIDs
// would lead to EXT-8246. So in this case we get them from speakers list.
else
{
LLIMModel::addSpeakersToRecent(mSessionID);
}
}
// If this ad-hoc is incoming then trying to get ids of people from mInitialTargetIDs
// would lead to EXT-8246. So in this case we get them from speakers list.
else
{
LLIMModel::addSpeakersToRecent(mSessionID);
}
}
//Mic default state is OFF on initiating/joining Ad-Hoc/Group calls
if (LLVoiceClient::getInstance()->getUserPTTState() && LLVoiceClient::getInstance()->getPTTIsToggle())
{
LLVoiceClient::getInstance()->inputUserControlState(true);
}
// Mic default state is OFF on initiating/joining Ad-Hoc/Group calls. It's on for P2P using the AdHoc infra.
LLVoiceClient::getInstance()->setUserPTTState(mIsP2P);
}
}
void LLVoiceChannelGroup::getChannelInfo()
void LLVoiceChannelGroup::requestChannelInfo()
{
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
std::string url = region->getCapability("ChatSessionRequest");
LLCoros::instance().launch("LLVoiceChannelGroup::voiceCallCapCoro",
boost::bind(&LLVoiceChannelGroup::voiceCallCapCoro, this, url));
LLCoros::instance().launch("LLVoiceChannelGroup::voiceCallCapCoro",
boost::bind(&LLVoiceChannelGroup::voiceCallCapCoro, this, url));
}
}
void LLVoiceChannelGroup::setChannelInfo(
const std::string& uri,
const std::string& credentials)
void LLVoiceChannelGroup::setChannelInfo(const LLSD& channelInfo)
{
setURI(uri);
mCredentials = credentials;
mChannelInfo = channelInfo;
if (mState == STATE_NO_CHANNEL_INFO)
{
if(!mURI.empty() && !mCredentials.empty())
if(!mChannelInfo.isUndefined())
{
setState(STATE_READY);
@ -516,9 +497,9 @@ void LLVoiceChannelGroup::setChannelInfo(
else if ( mIsRetrying )
{
// we have the channel info, just need to use it now
LLVoiceClient::getInstance()->setNonSpatialChannel(
mURI,
mCredentials);
LLVoiceClient::getInstance()->setNonSpatialChannel(channelInfo,
mCallDirection == OUTGOING_CALL,
mIsP2P);
}
}
@ -556,7 +537,7 @@ void LLVoiceChannelGroup::handleError(EStatusType status)
mIsRetrying = TRUE;
mIgnoreNextSessionLeave = TRUE;
getChannelInfo();
requestChannelInfo();
return;
}
else
@ -604,61 +585,62 @@ void LLVoiceChannelGroup::setState(EState state)
void LLVoiceChannelGroup::voiceCallCapCoro(std::string url)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("voiceCallCapCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("voiceCallCapCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLSD postData;
postData["method"] = "call";
postData["session-id"] = mSessionID;
LLSD postData;
postData["method"] = "call";
postData["session-id"] = mSessionID;
LLSD altParams;
altParams["preferred_voice_server_type"] = gSavedSettings.getString("VoiceServerType");
postData["alt_params"] = altParams;
LL_INFOS("Voice", "voiceCallCapCoro") << "Generic POST for " << url << LL_ENDL;
LL_INFOS("Voice", "voiceCallCapCoro") << "Generic POST for " << url << LL_ENDL;
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
if (!channelp)
{
LL_WARNS("Voice") << "Unable to retrieve channel with Id = " << mSessionID << LL_ENDL;
return;
}
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
if (!channelp)
{
LL_WARNS("Voice") << "Unable to retrieve channel with Id = " << mSessionID << LL_ENDL;
return;
}
if (!status)
{
if (status == LLCore::HttpStatus(HTTP_FORBIDDEN))
{
//403 == no ability
LLNotificationsUtil::add(
"VoiceNotAllowed",
channelp->getNotifyArgs());
}
else
{
LLNotificationsUtil::add(
"VoiceCallGenericError",
channelp->getNotifyArgs());
}
channelp->deactivate();
return;
}
if (!status)
{
if (status == LLCore::HttpStatus(HTTP_FORBIDDEN))
{
//403 == no ability
LLNotificationsUtil::add(
"VoiceNotAllowed",
channelp->getNotifyArgs());
}
else
{
LLNotificationsUtil::add(
"VoiceCallGenericError",
channelp->getNotifyArgs());
}
channelp->deactivate();
return;
}
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
LLSD::map_const_iterator iter;
for (iter = result.beginMap(); iter != result.endMap(); ++iter)
{
LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got "
<< iter->first << LL_ENDL;
}
channelp->setChannelInfo(
result["voice_credentials"]["channel_uri"].asString(),
result["voice_credentials"]["channel_credentials"].asString());
LLSD::map_const_iterator iter;
for (iter = result.beginMap(); iter != result.endMap(); ++iter)
{
LL_DEBUGS("Voice") << "LLVoiceChannelGroup::voiceCallCapCoro got "
<< iter->first << LL_ENDL;
}
LL_INFOS("Voice") << "LLVoiceChannelGroup::voiceCallCapCoro got " << result << LL_ENDL;
channelp->setChannelInfo(result["voice_credentials"]);
}
@ -682,13 +664,14 @@ void LLVoiceChannelProximal::activate()
if((LLVoiceChannel::sCurrentVoiceChannel != this) && (LLVoiceChannel::getState() == STATE_CONNECTED))
{
// we're connected to a non-spatial channel, so disconnect.
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
}
LLVoiceClient::getInstance()->activateSpatialChannel(true);
LLVoiceChannel::activate();
}
void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
void LLVoiceChannelProximal::onChange(EStatusType type, const LLSD& channelInfo, bool proximal)
{
if (!proximal)
{
@ -749,7 +732,7 @@ void LLVoiceChannelProximal::handleError(EStatusType status)
LLNotificationsUtil::add(notify, mNotifyArgs);
}
LLVoiceChannel::handleError(status);
// proximal voice remains up and the provider will try to reconnect.
}
void LLVoiceChannelProximal::deactivate()
@ -758,19 +741,23 @@ void LLVoiceChannelProximal::deactivate()
{
setState(STATE_HUNG_UP);
}
LLVoiceClient::getInstance()->activateSpatialChannel(false);
}
//
// LLVoiceChannelP2P
//
LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
LLVoiceChannelGroup(session_id, session_name),
mOtherUserID(other_user_id),
mReceivedCall(FALSE)
LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID &session_id,
const std::string &session_name,
const LLUUID &other_user_id,
LLVoiceP2POutgoingCallInterface* outgoing_call_interface) :
LLVoiceChannelGroup(session_id, session_name, true),
mOtherUserID(other_user_id),
mReceivedCall(FALSE),
mOutgoingCallInterface(outgoing_call_interface)
{
// make sure URI reflects encoded version of other user's agent id
setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
}
void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
@ -837,23 +824,23 @@ void LLVoiceChannelP2P::activate()
if (callStarted())
{
// no session handle yet, we're starting the call
if (mSessionHandle.empty())
if (mIncomingCallInterface == nullptr)
{
mReceivedCall = FALSE;
LLVoiceClient::getInstance()->callUser(mOtherUserID);
mOutgoingCallInterface->callUser(mOtherUserID);
}
// otherwise answering the call
else
{
if (!LLVoiceClient::getInstance()->answerInvite(mSessionHandle))
if (!mIncomingCallInterface->answerInvite())
{
mCallEndedByAgent = false;
mSessionHandle.clear();
mIncomingCallInterface.reset();
handleError(ERROR_UNKNOWN);
return;
}
// using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
mSessionHandle.clear();
// using the incoming call interface invalidates it. Clear it out here so we can't reuse it by accident.
mIncomingCallInterface.reset();
}
// Add the party to the list of people with which we've recently interacted.
@ -867,7 +854,17 @@ void LLVoiceChannelP2P::activate()
}
}
void LLVoiceChannelP2P::getChannelInfo()
void LLVoiceChannelP2P::deactivate()
{
if (callStarted())
{
mOutgoingCallInterface->hangup();
}
LLVoiceChannel::deactivate();
}
void LLVoiceChannelP2P::requestChannelInfo()
{
// pretend we have everything we need, since P2P doesn't use channel info
if (sCurrentVoiceChannel == this)
@ -877,8 +874,9 @@ void LLVoiceChannelP2P::getChannelInfo()
}
// receiving session from other user who initiated call
void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
void LLVoiceChannelP2P::setChannelInfo(const LLSD& channel_info)
{
mChannelInfo = channel_info;
BOOL needs_activate = FALSE;
if (callStarted())
{
@ -893,28 +891,16 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s
{
// we are active and have priority, invite the other user again
// under the assumption they will join this new session
mSessionHandle.clear();
LLVoiceClient::getInstance()->callUser(mOtherUserID);
mOutgoingCallInterface->callUser(mOtherUserID);
return;
}
}
mSessionHandle = handle;
// The URI of a p2p session should always be the other end's SIP URI.
if(!inURI.empty())
{
setURI(inURI);
}
else
{
LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL;
// See LLVoiceClient::sessionAddedEvent()
setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
}
mReceivedCall = TRUE;
if (!channel_info.isUndefined())
{
mIncomingCallInterface = LLVoiceClient::getInstance()->getIncomingCallInterface(channel_info);
}
if (needs_activate)
{
activate();
@ -932,7 +918,7 @@ void LLVoiceChannelP2P::setState(EState state)
if (mReceivedCall && state == STATE_RINGING)
{
//TODO: remove or redirect this call status notification
// LLCallInfoDialog::show("answering", mNotifyArgs);
// LLCallInfoDialog::show("answering", mNotifyArgs);
doSetState(state);
return;
}

View File

@ -66,16 +66,14 @@ public:
LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
virtual ~LLVoiceChannel();
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
virtual void onChange(EStatusType status, const LLSD& channelInfo, bool proximal);
virtual void handleStatusChange(EStatusType status);
virtual void handleError(EStatusType status);
virtual void deactivate();
virtual void activate();
virtual void setChannelInfo(
const std::string& uri,
const std::string& credentials);
virtual void getChannelInfo();
virtual void setChannelInfo(const LLSD &channelInfo);
virtual void requestChannelInfo();
virtual BOOL isActive();
virtual BOOL callStarted();
@ -96,43 +94,37 @@ public:
EDirection getCallDirection() {return mCallDirection;}
static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
static LLVoiceChannel* getChannelByURI(std::string uri);
static LLVoiceChannel* getCurrentVoiceChannel();
static void initClass();
static void suspend();
static void resume();
protected:
protected:
virtual void setState(EState state);
/**
* Use this method if you want mStateChangedCallback to be executed while state is changed
*/
void doSetState(const EState& state);
void setURI(std::string uri);
// there can be two directions INCOMING and OUTGOING
EDirection mCallDirection;
std::string mURI;
std::string mCredentials;
LLUUID mSessionID;
EState mState;
std::string mSessionName;
LLSD mNotifyArgs;
LLSD mCallDialogPayload;
LLSD mNotifyArgs;
LLSD mChannelInfo;
// true if call was ended by agent
bool mCallEndedByAgent;
BOOL mIgnoreNextSessionLeave;
bool mIgnoreNextSessionLeave;
LLHandle<LLPanel> mLoginNotificationHandle;
typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
static voice_channel_map_t sVoiceChannelMap;
typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
static voice_channel_map_uri_t sVoiceChannelURIMap;
static LLVoiceChannel* sProximalVoiceChannel;
static LLVoiceChannel* sCurrentVoiceChannel;
static LLVoiceChannel* sSuspendedVoiceChannel;
static BOOL sSuspended;
@ -144,55 +136,58 @@ private:
class LLVoiceChannelGroup : public LLVoiceChannel
{
public:
LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
LLVoiceChannelGroup(const LLUUID& session_id,
const std::string& session_name,
bool is_p2p);
/*virtual*/ void handleStatusChange(EStatusType status);
/*virtual*/ void handleError(EStatusType status);
/*virtual*/ void activate();
/*virtual*/ void deactivate();
/*vritual*/ void setChannelInfo(
const std::string& uri,
const std::string& credentials);
/*virtual*/ void getChannelInfo();
void handleStatusChange(EStatusType status) override;
void handleError(EStatusType status) override;
void activate() override;
void deactivate() override;
void setChannelInfo(const LLSD &channelInfo) override;
void requestChannelInfo() override;
protected:
virtual void setState(EState state);
void setState(EState state) override;
private:
void voiceCallCapCoro(std::string url);
U32 mRetries;
BOOL mIsRetrying;
bool mIsP2P;
};
class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
{
LLSINGLETON(LLVoiceChannelProximal);
public:
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal) override;
/*virtual*/ void handleStatusChange(EStatusType status) override;
/*virtual*/ void handleError(EStatusType status) override;
/*virtual*/ BOOL isActive() override;
/*virtual*/ void activate() override;
/*virtual*/ void deactivate() override;
LLSINGLETON_C11(LLVoiceChannelProximal);
public:
void onChange(EStatusType status, const LLSD &channelInfo, bool proximal) override;
void handleStatusChange(EStatusType status) override;
void handleError(EStatusType status) override;
BOOL isActive() override;
void activate() override;
void deactivate() override;
};
class LLVoiceChannelP2P : public LLVoiceChannelGroup
{
public:
LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
public:
LLVoiceChannelP2P(const LLUUID &session_id,
const std::string &session_name,
const LLUUID &other_user_id,
LLVoiceP2POutgoingCallInterface * outgoing_call_interface);
/*virtual*/ void handleStatusChange(EStatusType status) override;
/*virtual*/ void handleError(EStatusType status) override;
/*virtual*/ void activate() override;
/*virtual*/ void getChannelInfo() override;
void handleStatusChange(EStatusType status) override;
void handleError(EStatusType status) override;
void activate() override;
void requestChannelInfo() override;
void deactivate() override;
void setChannelInfo(const LLSD& channel_info) override;
void setSessionHandle(const std::string& handle, const std::string &inURI);
protected:
virtual void setState(EState state) override;
protected:
void setState(EState state) override;
private:
@ -201,10 +196,10 @@ private:
*
**/
void addToTheRecentPeopleList();
std::string mSessionHandle;
LLUUID mOtherUserID;
BOOL mReceivedCall;
LLVoiceP2POutgoingCallInterface *mOutgoingCallInterface;
LLVoiceP2PIncomingCallInterfacePtr mIncomingCallInterface;
};
#endif // LL_VOICECHANNEL_H

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,25 @@
/**
/**
* @file llvoiceclient.h
* @brief Declaration of LLVoiceClient class which is the interface to the voice client process.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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$
*/
@ -34,9 +34,11 @@ 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"
#include <boost/shared_ptr.hpp>
// devices
@ -89,18 +91,53 @@ public:
} EStatusType;
virtual ~LLVoiceClientStatusObserver() { }
virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) = 0;
virtual void onChange(EStatusType status, const LLSD& channelInfo, bool proximal) = 0;
static std::string status2string(EStatusType inStatus);
};
struct LLVoiceVersionInfo
{
std::string serverType;
std::string voiceServerType;
std::string internalVoiceServerType;
int majorVersion;
int minorVersion;
std::string serverVersion;
std::string mBuildVersion;
};
//////////////////////////////////
/// @class LLVoiceP2POutgoingCallInterface
/// @brief Outgoing call interface
///
/// For providers that support P2P signaling (vivox)
/////////////////////////////////
class LLVoiceP2POutgoingCallInterface
{
public:
// initiate an outgoing call to a user
virtual void callUser(const LLUUID &agentID) = 0;
virtual void hangup() = 0;
};
//////////////////////////////////
/// @class LLVoiceP2PIncomingCallInterface
/// @brief Incoming call interface
///
/// For providers that support P2P signaling (vivox)
/////////////////////////////////
class LLVoiceP2PIncomingCallInterface
{
public:
virtual ~LLVoiceP2PIncomingCallInterface() {}
virtual bool answerInvite() = 0;
virtual void declineInvite() = 0;
};
typedef boost::shared_ptr<LLVoiceP2PIncomingCallInterface> LLVoiceP2PIncomingCallInterfacePtr;
//////////////////////////////////
/// @class LLVoiceModuleInterface
/// @brief Voice module interface
@ -113,30 +150,32 @@ class LLVoiceModuleInterface
public:
LLVoiceModuleInterface() {}
virtual ~LLVoiceModuleInterface() {}
virtual void init(LLPumpIO *pump)=0; // Call this once at application startup (creates connector)
virtual void terminate()=0; // Call this to clean up during shutdown
virtual void updateSettings()=0; // call after loading settings and whenever they change
virtual bool isVoiceWorking() const = 0; // connected to a voice server and voice channel
virtual void setHidden(bool hidden)=0; // Hides the user from voice.
virtual const LLVoiceVersionInfo& getVersion()=0;
/////////////////////
/// @name Tuning
//@{
virtual void tuningStart()=0;
virtual void tuningStop()=0;
virtual bool inTuningMode()=0;
virtual void tuningSetMicVolume(float volume)=0;
virtual void tuningSetSpeakerVolume(float volume)=0;
virtual float tuningGetEnergy(void)=0;
//@}
/////////////////////
/// @name Devices
//@{
@ -144,119 +183,110 @@ public:
// i.e. when the daemon is running and connected, and the device lists are populated.
virtual bool deviceSettingsAvailable()=0;
virtual bool deviceSettingsUpdated() = 0;
// Requery the vivox daemon for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
virtual void refreshDeviceLists(bool clearCurrentList = true)=0;
virtual void setCaptureDevice(const std::string& name)=0;
virtual void setRenderDevice(const std::string& name)=0;
virtual LLVoiceDeviceList& getCaptureDevices()=0;
virtual LLVoiceDeviceList& getRenderDevices()=0;
virtual void getParticipantList(std::set<LLUUID> &participants)=0;
virtual bool isParticipant(const LLUUID& speaker_id)=0;
//@}
////////////////////////////
/// @ name Channel stuff
//@{
// returns true iff the user is currently in a proximal (local spatial) channel.
// Note that gestures should only fire if this returns true.
virtual bool inProximalChannel()=0;
virtual void setNonSpatialChannel(const std::string &uri,
const std::string &credentials)=0;
virtual bool setSpatialChannel(const std::string &uri,
const std::string &credentials)=0;
virtual void leaveNonSpatialChannel()=0;
virtual void leaveChannel(void)=0;
// Returns the URI of the current channel, or an empty string if not currently in a channel.
// NOTE that it will return an empty string if it's in the process of joining a channel.
virtual std::string getCurrentChannel()=0;
virtual void setNonSpatialChannel(const LLSD& channelInfo,
bool notify_on_first_join,
bool hangup_on_last_leave)=0;
virtual bool setSpatialChannel(const LLSD& channelInfo)=0;
virtual void leaveNonSpatialChannel() = 0;
virtual void processChannels(bool process) = 0;
virtual bool isCurrentChannel(const LLSD &channelInfo) = 0;
virtual bool compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2) = 0;
//@}
//////////////////////////
/// @name invitations
/// @name p2p
//@{
// start a voice channel with the specified user
virtual void callUser(const LLUUID &uuid)=0;
virtual bool isValidChannel(std::string& channelHandle)=0;
virtual bool answerInvite(std::string &channelHandle)=0;
virtual void declineInvite(std::string &channelHandle)=0;
// initiate a call with a peer using the P2P interface, which only applies to some
// voice server types. Otherwise, a group call should be used for P2P
virtual LLVoiceP2POutgoingCallInterface* getOutgoingCallInterface() = 0;
// an incoming call was received, and the incoming call dialogue is asking for an interface to
// answer or decline.
virtual LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voice_call_info) = 0;
//@}
/////////////////////////
/// @name Volume/gain
//@{
virtual void setVoiceVolume(F32 volume)=0;
virtual void setMicGain(F32 volume)=0;
//@}
/////////////////////////
/// @name enable disable voice and features
//@{
// <FS:Ansariel> Bypass LLCachedControls for voice status update
//virtual bool voiceEnabled()=0;
virtual bool voiceEnabled(bool no_cache = false)=0;
// </FS:Ansariel>
virtual void setVoiceEnabled(bool enabled)=0;
virtual void setLipSyncEnabled(BOOL enabled)=0;
virtual BOOL lipSyncEnabled()=0;
virtual void setMuteMic(bool muted)=0; // Set the mute state of the local mic.
//@}
//////////////////////////
/// @name nearby speaker accessors
//@{
virtual BOOL getVoiceEnabled(const LLUUID& id)=0; // true if we've received data for this avatar
virtual std::string getDisplayName(const LLUUID& id)=0;
virtual BOOL isParticipantAvatar(const LLUUID &id)=0;
virtual BOOL getIsSpeaking(const LLUUID& id)=0;
virtual BOOL getIsModeratorMuted(const LLUUID& id)=0;
virtual F32 getCurrentPower(const LLUUID& id)=0; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
virtual BOOL getOnMuteList(const LLUUID& id)=0;
virtual F32 getUserVolume(const LLUUID& id)=0;
virtual void setUserVolume(const LLUUID& id, F32 volume)=0; // set's volume for specified agent, from 0-1 (where .5 is nominal)
virtual void setUserVolume(const LLUUID& id, F32 volume)=0; // set's volume for specified agent, from 0-1 (where .5 is nominal)
//@}
//////////////////////////
/// @name text chat
//@{
virtual BOOL isSessionTextIMPossible(const LLUUID& id)=0;
virtual BOOL isSessionCallBackPossible(const LLUUID& id)=0;
//virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message)=0;
virtual void endUserIMSession(const LLUUID &uuid)=0;
//@}
// authorize the user
virtual void userAuthorized(const std::string& user_id,
const LLUUID &agentID)=0;
//////////////////////////////
/// @name Status notification
//@{
virtual void addObserver(LLVoiceClientStatusObserver* observer)=0;
virtual void removeObserver(LLVoiceClientStatusObserver* observer)=0;
virtual void addObserver(LLFriendObserver* observer)=0;
virtual void removeObserver(LLFriendObserver* observer)=0;
virtual void removeObserver(LLFriendObserver* observer)=0;
virtual void addObserver(LLVoiceClientParticipantObserver* observer)=0;
virtual void removeObserver(LLVoiceClientParticipantObserver* observer)=0;
// <FS:Ansariel> Add callback for user volume change
virtual boost::signals2::connection setUserVolumeUpdateCallback(const user_voice_volume_change_callback_t::slot_type& cb) = 0;
virtual void removeObserver(LLVoiceClientParticipantObserver* observer)=0;
//@}
virtual std::string sipURIFromID(const LLUUID &id)=0;
//@}
};
@ -340,9 +370,9 @@ public:
micro_changed_signal_t mMicroChangedSignal;
void terminate(); // Call this to clean up during shutdown
const LLVoiceVersionInfo getVersion();
static const F32 OVERDRIVEN_POWER_LEVEL;
// <FS:Ansariel> Centralized voice power level
@ -363,18 +393,18 @@ public:
void tuningStart();
void tuningStop();
bool inTuningMode();
void tuningSetMicVolume(float volume);
void tuningSetSpeakerVolume(float volume);
float tuningGetEnergy(void);
// devices
// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
// i.e. when the daemon is running and connected, and the device lists are populated.
bool deviceSettingsAvailable();
bool deviceSettingsUpdated(); // returns true when the device list has been updated recently.
// Requery the vivox daemon for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
@ -391,65 +421,65 @@ public:
////////////////////////////
// Channel stuff
//
// returns true iff the user is currently in a proximal (local spatial) channel.
// Note that gestures should only fire if this returns true.
bool inProximalChannel();
void setNonSpatialChannel(
const std::string &uri,
const std::string &credentials);
void setSpatialChannel(
const std::string &uri,
const std::string &credentials);
void setNonSpatialChannel(const LLSD& channelInfo,
bool notify_on_first_join,
bool hangup_on_last_leave);
void setSpatialChannel(const LLSD &channelInfo);
void activateSpatialChannel(bool activate);
void leaveNonSpatialChannel();
// Returns the URI of the current channel, or an empty string if not currently in a channel.
// NOTE that it will return an empty string if it's in the process of joining a channel.
std::string getCurrentChannel();
// start a voice channel with the specified user
void callUser(const LLUUID &uuid);
bool isValidChannel(std::string& channelHandle);
bool answerInvite(std::string &channelHandle);
void declineInvite(std::string &channelHandle);
void leaveChannel(void); // call this on logout or teleport begin
bool isCurrentChannel(const LLSD& channelInfo);
bool compareChannels(const LLSD& channelInfo1, const LLSD& channelInfo2);
// initiate a call with a peer using the P2P interface, which only applies to some
// voice server types. Otherwise, a group call should be used for P2P
LLVoiceP2POutgoingCallInterface* getOutgoingCallInterface(const LLSD& voiceChannelInfo);
LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voiceCallInfo);
/////////////////////////////
// Sending updates of current state
void setVoiceVolume(F32 volume);
void setMicGain(F32 volume);
void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
// <FS:Ansariel> Bypass LLCachedControls for voice status update
//bool voiceEnabled();
bool voiceEnabled(bool no_cache = false);
// </FS:Ansariel>
void setLipSyncEnabled(BOOL enabled);
void setMuteMic(bool muted); // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
void setUserPTTState(bool ptt);
bool getUserPTTState();
void toggleUserPTTState(void);
void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
void setVoiceEnabled(bool enabled);
void setUsePTT(bool usePTT);
void setPTTIsToggle(bool PTTIsToggle);
bool getPTTIsToggle();
bool getPTTIsToggle();
void updateMicMuteLogic();
BOOL lipSyncEnabled();
boost::signals2::connection MicroChangedCallback(const micro_changed_signal_t::slot_type& cb ) { return mMicroChangedSignal.connect(cb); }
// <FS:Ansariel> Add callback for user volume change
boost::signals2::connection setUserVolumeUpdateCallback(const user_voice_volume_change_callback_t::slot_type& cb);
static boost::signals2::connection setUserVolumeUpdateCallback(const user_voice_volume_change_callback_t::slot_type& cb);
static user_voice_volume_change_callback_t sUserVolumeUpdateSignal;
/////////////////////////////
// Accessors for data related to nearby speakers
BOOL getVoiceEnabled(const LLUUID& id); // true if we've received data for this avatar
std::string getDisplayName(const LLUUID& id);
std::string getDisplayName(const LLUUID& id);
BOOL isOnlineSIP(const LLUUID &id);
BOOL isParticipantAvatar(const LLUUID &id);
BOOL getIsSpeaking(const LLUUID& id);
@ -463,32 +493,33 @@ public:
// </FS:Ansariel> Centralized voice power level
/////////////////////////////
BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled.
// Use this to determine whether to show a "no speech" icon in the menu bar.
void getParticipantList(std::set<LLUUID> &participants);
bool isParticipant(const LLUUID& speaker_id);
//////////////////////////
/// @name text chat
//@{
BOOL isSessionTextIMPossible(const LLUUID& id);
BOOL isSessionCallBackPossible(const LLUUID& id);
//BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return true;} ;
void endUserIMSession(const LLUUID &uuid);
//@}
void setSpatialVoiceModule(const std::string& voice_server_type);
void setNonSpatialVoiceModule(const std::string &voice_server_type);
void userAuthorized(const std::string& user_id,
const LLUUID &agentID);
const LLUUID &agentID);
void onRegionChanged();
void addObserver(LLVoiceClientStatusObserver* observer);
void removeObserver(LLVoiceClientStatusObserver* observer);
void addObserver(LLFriendObserver* observer);
void removeObserver(LLFriendObserver* observer);
void addObserver(LLVoiceClientParticipantObserver* observer);
void removeObserver(LLVoiceClientParticipantObserver* observer);
std::string sipURIFromID(const LLUUID &id);
std::string sipURIFromID(const LLUUID &id);
//////////////////////////
/// @name Voice effects
@ -499,20 +530,30 @@ public:
// Returns NULL if voice effects are not supported, or not enabled.
LLVoiceEffectInterface* getVoiceEffectInterface() const;
//@}
private:
void handleSimulatorFeaturesReceived(const LLSD &simulatorFeatures);
private:
void init(LLPumpIO *pump);
protected:
LLVoiceModuleInterface* mVoiceModule;
LLVoiceModuleInterface* mSpatialVoiceModule;
LLVoiceModuleInterface* mNonSpatialVoiceModule;
LLSD mSpatialCredentials; // used to store spatial credentials for vivox
// so they're available when the region voice
// server is retrieved.
LLPumpIO *m_servicePump;
boost::signals2::connection mSimulatorFeaturesReceivedSlot;
LLCachedControl<bool> mVoiceEffectEnabled;
LLCachedControl<std::string> mVoiceEffectDefault;
bool mPTTDirty;
bool mPTT;
bool mUsePTT;
S32 mPTTMouseButton;
KEY mPTTKey;

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,25 @@
/**
/**
* @file llvoicevivox.h
* @brief Declaration of LLDiamondwareVoiceClient class which is the interface to the voice client process.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, 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$
*/
@ -51,12 +51,27 @@ class LLVivoxProtocolParser;
class LLAvatarName;
class LLVivoxVoiceClientMuteListObserver;
extern const std::string VIVOX_VOICE_SERVER_TYPE;
class LLVivoxVoiceP2PIncomingCall : public LLVoiceP2PIncomingCallInterface
{
public:
LLVivoxVoiceP2PIncomingCall(const LLSD& call_info) : mCallInfo(call_info) {}
~LLVivoxVoiceP2PIncomingCall() override {}
bool answerInvite() override;
void declineInvite() override;
protected:
LLSD mCallInfo;
};
class LLVivoxVoiceClient : public LLSingleton<LLVivoxVoiceClient>,
virtual public LLVoiceModuleInterface,
virtual public LLVoiceEffectInterface
virtual public LLVoiceEffectInterface,
virtual public LLVoiceP2POutgoingCallInterface
{
LLSINGLETON(LLVivoxVoiceClient);
LLSINGLETON_C11(LLVivoxVoiceClient);
LOG_CLASS(LLVivoxVoiceClient);
virtual ~LLVivoxVoiceClient();
@ -64,159 +79,149 @@ public:
/// @name LLVoiceModuleInterface virtual implementations
/// @see LLVoiceModuleInterface
//@{
virtual void init(LLPumpIO *pump) override; // Call this once at application startup (creates connector)
virtual void terminate() override; // Call this to clean up during shutdown
virtual const LLVoiceVersionInfo& getVersion() override;
virtual void updateSettings() override; // call after loading settings and whenever they change
void init(LLPumpIO *pump) override; // Call this once at application startup (creates connector)
void terminate() override; // Call this to clean up during shutdown
// Returns true if vivox has successfully logged in and is not in error state
virtual bool isVoiceWorking() const override;
const LLVoiceVersionInfo& getVersion() override;
void updateSettings() override; // call after loading settings and whenever they change
// Returns true if vivox has successfully logged in and is not in error state
bool isVoiceWorking() const override;
/////////////////////
/// @name Tuning
//@{
virtual void tuningStart() override;
virtual void tuningStop() override;
virtual bool inTuningMode() override;
virtual void tuningSetMicVolume(float volume) override;
virtual void tuningSetSpeakerVolume(float volume) override;
virtual float tuningGetEnergy(void) override;
void tuningStart() override;
void tuningStop() override;
bool inTuningMode() override;
void tuningSetMicVolume(float volume) override;
void tuningSetSpeakerVolume(float volume) override;
float tuningGetEnergy(void) override;
//@}
/////////////////////
/// @name Devices
//@{
// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
// i.e. when the daemon is running and connected, and the device lists are populated.
virtual bool deviceSettingsAvailable() override;
virtual bool deviceSettingsUpdated() override; //return if the list has been updated and never fetched, only to be called from the voicepanel.
bool deviceSettingsAvailable() override;
bool deviceSettingsUpdated() override; //return if the list has been updated and never fetched, only to be called from the voicepanel.
// Requery the vivox daemon for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
virtual void refreshDeviceLists(bool clearCurrentList = true) override;
virtual void setCaptureDevice(const std::string& name) override;
virtual void setRenderDevice(const std::string& name) override;
virtual LLVoiceDeviceList& getCaptureDevices() override;
virtual LLVoiceDeviceList& getRenderDevices() override;
//@}
virtual void getParticipantList(std::set<LLUUID> &participants) override;
virtual bool isParticipant(const LLUUID& speaker_id) override;
void refreshDeviceLists(bool clearCurrentList = true) override;
void setCaptureDevice(const std::string& name) override;
void setRenderDevice(const std::string& name) override;
LLVoiceDeviceList& getCaptureDevices() override;
LLVoiceDeviceList& getRenderDevices() override;
//@}
void getParticipantList(std::set<LLUUID> &participants) override;
bool isParticipant(const LLUUID& speaker_id) override;
// Send a text message to the specified user, initiating the session if necessary.
// virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;};
// close any existing text IM session with the specified user
virtual void endUserIMSession(const LLUUID &uuid) override;
// Returns true if calling back the session URI after the session has closed is possible.
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
virtual BOOL isSessionCallBackPossible(const LLUUID &session_id) override;
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
BOOL isSessionCallBackPossible(const LLUUID &session_id) override;
// Returns true if the session can accepte text IM's.
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
virtual BOOL isSessionTextIMPossible(const LLUUID &session_id) override;
// NOTE: this will return true if the session can't be found.
BOOL isSessionTextIMPossible(const LLUUID &session_id) override;
////////////////////////////
/// @name Channel stuff
//@{
// returns true iff the user is currently in a proximal (local spatial) channel.
// Note that gestures should only fire if this returns true.
virtual bool inProximalChannel() override;
virtual void setNonSpatialChannel(const std::string &uri,
const std::string &credentials) override;
virtual bool setSpatialChannel(const std::string &uri,
const std::string &credentials) override;
virtual void leaveNonSpatialChannel() override;
virtual void leaveChannel(void) override;
// Returns the URI of the current channel, or an empty string if not currently in a channel.
// NOTE that it will return an empty string if it's in the process of joining a channel.
virtual std::string getCurrentChannel() override;
bool inProximalChannel() override;
void setNonSpatialChannel(const LLSD& channelInfo,
bool notify_on_first_join,
bool hangup_on_last_leave) override;
bool setSpatialChannel(const LLSD& channelInfo) override;
void leaveNonSpatialChannel() override;
void processChannels(bool process) override;
void leaveChannel(void);
bool isCurrentChannel(const LLSD &channelInfo) override;
bool compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2) override;
//@}
//////////////////////////
/// @name invitations
/// @name LLVoiceP2POutgoingCallInterface
//@{
// start a voice channel with the specified user
virtual void callUser(const LLUUID &uuid) override;
virtual bool isValidChannel(std::string &channelHandle) override;
virtual bool answerInvite(std::string &channelHandle) override;
virtual void declineInvite(std::string &channelHandle) override;
void callUser(const LLUUID &uuid) override;
void hangup() override;
//@}
LLVoiceP2POutgoingCallInterface *getOutgoingCallInterface() override { return this; }
LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voice_call_info) override;
bool answerInvite(const std::string &sessionHandle);
void declineInvite(const std::string &sessionHandle);
/////////////////////////
/// @name Volume/gain
//@{
virtual void setVoiceVolume(F32 volume) override;
virtual void setMicGain(F32 volume) override;
void setVoiceVolume(F32 volume) override;
void setMicGain(F32 volume) override;
//@}
/////////////////////////
/// @name enable disable voice and features
//@{
// <FS:Ansariel> Bypass LLCachedControls for voice status update
//virtual bool voiceEnabled() override;
virtual bool voiceEnabled(bool no_cache = false) override;
// </FS:Ansariel>
virtual void setVoiceEnabled(bool enabled) override;
virtual BOOL lipSyncEnabled() override;
virtual void setLipSyncEnabled(BOOL enabled) override;
virtual void setMuteMic(bool muted) override; // Set the mute state of the local mic.
void setVoiceEnabled(bool enabled) override;
void setMuteMic(bool muted) override; // Set the mute state of the local mic.
//@}
//////////////////////////
/// @name nearby speaker accessors
//@{
virtual BOOL getVoiceEnabled(const LLUUID& id) override; // true if we've received data for this avatar
virtual std::string getDisplayName(const LLUUID& id) override;
virtual BOOL isParticipantAvatar(const LLUUID &id) override;
virtual BOOL getIsSpeaking(const LLUUID& id) override;
virtual BOOL getIsModeratorMuted(const LLUUID& id) override;
virtual F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
virtual BOOL getOnMuteList(const LLUUID& id) override;
virtual F32 getUserVolume(const LLUUID& id) override;
virtual void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)
std::string getDisplayName(const LLUUID& id) override;
BOOL isParticipantAvatar(const LLUUID &id) override;
BOOL getIsSpeaking(const LLUUID& id) override;
BOOL getIsModeratorMuted(const LLUUID& id) override;
F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
F32 getUserVolume(const LLUUID& id) override;
void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)
//@}
// authorize the user
virtual void userAuthorized(const std::string& user_id,
const LLUUID &agentID) override;
void userAuthorized(const std::string& user_id,
const LLUUID &agentID) override;
//////////////////////////////
/// @name Status notification
//@{
virtual void addObserver(LLVoiceClientStatusObserver* observer) override;
virtual void removeObserver(LLVoiceClientStatusObserver* observer) override;
virtual void addObserver(LLFriendObserver* observer) override;
virtual void removeObserver(LLFriendObserver* observer) override;
virtual void addObserver(LLVoiceClientParticipantObserver* observer) override;
virtual void removeObserver(LLVoiceClientParticipantObserver* observer) override;
// <FS:Ansariel> Add callback for user volume change
boost::signals2::connection setUserVolumeUpdateCallback(const user_voice_volume_change_callback_t::slot_type& cb) override
{
return mUserVolumeUpdateSignal.connect(cb);
}
// </FS:Ansariel>
void addObserver(LLVoiceClientStatusObserver* observer) override;
void removeObserver(LLVoiceClientStatusObserver* observer) override;
void addObserver(LLFriendObserver* observer) override;
void removeObserver(LLFriendObserver* observer) override;
void addObserver(LLVoiceClientParticipantObserver* observer) override;
void removeObserver(LLVoiceClientParticipantObserver* observer) override;
//@}
virtual std::string sipURIFromID(const LLUUID &id) override;
std::string sipURIFromID(const LLUUID &id) override;
//@}
/// @name LLVoiceEffectInterface virtual implementations
@ -226,32 +231,32 @@ public:
//////////////////////////
/// @name Accessors
//@{
virtual bool setVoiceEffect(const LLUUID& id) override;
virtual const LLUUID getVoiceEffect() override;
virtual LLSD getVoiceEffectProperties(const LLUUID& id) override;
bool setVoiceEffect(const LLUUID& id) override;
const LLUUID getVoiceEffect() override;
LLSD getVoiceEffectProperties(const LLUUID& id) override;
virtual void refreshVoiceEffectLists(bool clear_lists) override;
virtual const voice_effect_list_t& getVoiceEffectList() const override;
virtual const voice_effect_list_t& getVoiceEffectTemplateList() const override;
void refreshVoiceEffectLists(bool clear_lists) override;
const voice_effect_list_t& getVoiceEffectList() const override;
const voice_effect_list_t& getVoiceEffectTemplateList() const override;
//@}
//////////////////////////////
/// @name Status notification
//@{
virtual void addObserver(LLVoiceEffectObserver* observer) override;
virtual void removeObserver(LLVoiceEffectObserver* observer) override;
void addObserver(LLVoiceEffectObserver* observer) override;
void removeObserver(LLVoiceEffectObserver* observer) override;
//@}
//////////////////////////////
/// @name Effect preview buffer
//@{
virtual void enablePreviewBuffer(bool enable) override;
virtual void recordPreviewBuffer() override;
virtual void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) override;
virtual void stopPreviewBuffer() override;
void enablePreviewBuffer(bool enable) override;
void recordPreviewBuffer() override;
void playPreviewBuffer(const LLUUID& effect_id = LLUUID::null) override;
void stopPreviewBuffer() override;
virtual bool isPreviewRecording() override;
virtual bool isPreviewPlaying() override;
bool isPreviewRecording() override;
bool isPreviewPlaying() override;
//@}
//@}
@ -261,12 +266,12 @@ public:
protected:
//////////////////////
// Vivox Specific definitions
friend class LLVivoxVoiceClientMuteListObserver;
friend class LLVivoxVoiceClientFriendsObserver;
// Vivox Specific definitions
friend class LLVivoxVoiceClientMuteListObserver;
friend class LLVivoxVoiceClientFriendsObserver;
enum streamState
{
streamStateUnknown = 0,
@ -275,16 +280,16 @@ protected:
streamStateRinging = 3,
streamStateConnecting = 6, // same as Vivox session_media_connecting enum
streamStateDisconnecting = 7, //Same as Vivox session_media_disconnecting enum
};
};
struct participantState
{
public:
participantState(const std::string &uri);
bool updateMuteState(); // true if mute state has changed
bool isAvatar();
std::string mURI;
LLUUID mAvatarID;
std::string mAccountName;
@ -309,7 +314,7 @@ protected:
typedef std::map<const std::string, participantStatePtr_t> participantMap;
typedef std::map<const LLUUID, participantStatePtr_t> participantUUIDMap;
struct sessionState
{
public:
@ -320,7 +325,9 @@ protected:
static ptr_t createSession();
~sessionState();
LLSD getVoiceChannelInfo();
participantStatePtr_t addParticipant(const std::string &uri);
void removeParticipant(const participantStatePtr_t &participant);
void removeAllParticipants();
@ -335,7 +342,8 @@ protected:
bool isCallBackPossible();
bool isTextIMPossible();
bool isSpatial() { return mIsSpatial; }
static void for_each(sessionFunc_t func);
std::string mHandle;
@ -347,7 +355,7 @@ protected:
std::string mHash; // Channel password
std::string mErrorStatusString;
std::queue<std::string> mTextMsgQueue;
LLUUID mIMSessionID;
LLUUID mCallerID;
int mErrorStatusCode;
@ -394,7 +402,7 @@ protected:
typedef boost::shared_ptr<sessionState> sessionStatePtr_t;
typedef std::map<std::string, sessionStatePtr_t> sessionMap;
///////////////////////////////////////////////////////
// Private Member Functions
//////////////////////////////////////////////////////
@ -406,17 +414,17 @@ protected:
//@{
// Call this if the connection to the daemon terminates unexpectedly. It will attempt to reset everything and relaunch.
void daemonDied();
// Call this if we're just giving up on voice (can't provision an account, etc.). It will clean up and go away.
void giveUp();
void giveUp();
// write to the tvc
bool writeString(const std::string &str);
void connectorCreate();
void connectorShutdown();
void closeSocket(void);
void connectorShutdown();
void closeSocket(void);
// void requestVoiceAccountProvision(S32 retries = 3);
void setLoginInfo(
const std::string& account_name,
@ -425,14 +433,14 @@ protected:
const std::string& voice_account_server_uri);
void loginSendMessage();
void logout();
void logoutSendMessage();
void logoutSendMessage();
//@}
//------------------------------------
// tuning
void tuningRenderStartSendMessage(const std::string& name, bool loop);
void tuningRenderStopSendMessage();
@ -445,12 +453,12 @@ protected:
void addCaptureDevice(const LLVoiceDevice& device);
void clearRenderDevices();
void setDevicesListUpdated(bool state);
void addRenderDevice(const LLVoiceDevice& device);
void addRenderDevice(const LLVoiceDevice& device);
void buildSetAudioDevices(std::ostringstream &stream);
void getCaptureDevicesSendMessage();
void getRenderDevicesSendMessage();
// local audio updates, mic mute, speaker mute, mic volume and speaker volumes
void sendLocalAudioUpdates();
@ -477,9 +485,9 @@ protected:
void auxAudioPropertiesEvent(F32 energy);
void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string &notificationType);
void muteListChanged();
/////////////////////////////
// VAD changes
// disable auto-VAD and configure VAD parameters explicitly
@ -495,7 +503,7 @@ protected:
void setEarLocation(S32 loc);
/////////////////////////////
// Accessors for data related to nearby speakers
@ -503,31 +511,26 @@ protected:
BOOL getUsingPTT(const LLUUID& id);
std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable)
/////////////////////////////
BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled.
// Use this to determine whether to show a "no speech" icon in the menu bar.
/////////////////////////////
// Recording controls
void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
void recordingLoopSave(const std::string& filename);
void recordingStop();
// Playback controls
void filePlaybackStart(const std::string& filename);
void filePlaybackStop();
void filePlaybackSetPaused(bool paused);
void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
participantStatePtr_t findParticipantByID(const LLUUID& id);
#if 0
////////////////////////////////////////
// voice sessions.
typedef std::set<sessionStatePtr_t> sessionSet;
typedef sessionSet::iterator sessionIterator;
sessionIterator sessionsBegin(void);
sessionIterator sessionsEnd(void);
@ -536,7 +539,7 @@ protected:
sessionStatePtr_t findSession(const std::string &handle);
sessionStatePtr_t findSessionBeingCreatedByURI(const std::string &uri);
sessionStatePtr_t findSession(const LLUUID &participant_id);
sessionStatePtr_t addSession(const std::string &uri, const std::string &handle = std::string());
void clearSessionHandle(const sessionStatePtr_t &session);
void setSessionHandle(const sessionStatePtr_t &session, const std::string &handle);
@ -552,11 +555,11 @@ protected:
// This is called in several places where the session _may_ need to be deleted.
// It contains logic for whether to delete the session or keep it around.
void reapSession(const sessionStatePtr_t &session);
// Returns true if the session seems to indicate we've moved to a region on a different voice server
bool sessionNeedsRelog(const sessionStatePtr_t &session);
//////////////////////////////////////
// buddy list stuff, needed for SLIM later
struct buddyListEntry
@ -576,13 +579,13 @@ protected:
};
typedef std::map<std::string, buddyListEntry*> buddyListMap;
/////////////////////////////
// session control messages
void accountListBlockRulesSendMessage();
void accountListAutoAcceptRulesSendMessage();
void sessionGroupCreateSendMessage();
void sessionCreateSendMessage(const sessionStatePtr_t &session, bool startAudio = true, bool startText = false);
void sessionGroupAddSessionSendMessage(const sessionStatePtr_t &session, bool startAudio = true, bool startText = false);
@ -593,20 +596,20 @@ protected:
void sessionMediaDisconnectSendMessage(const sessionStatePtr_t &session);
// void sessionTextDisconnectSendMessage(sessionState *session);
// Pokes the state machine to leave the audio session next time around.
void sessionTerminate();
void sessionTerminate();
// Pokes the state machine to shut down the connector and restart it.
void requestRelog();
// Does the actual work to get out of the audio session
void leaveAudioSession();
friend class LLVivoxVoiceClientCapResponder;
void lookupName(const LLUUID &id);
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
void avatarNameResolved(const LLUUID &id, const std::string &name);
@ -626,10 +629,10 @@ protected:
const S32 font_status,
const bool template_font = false);
void accountGetSessionFontsResponse(int statusCode, const std::string &statusString);
void accountGetTemplateFontsResponse(int statusCode, const std::string &statusString);
void accountGetTemplateFontsResponse(int statusCode, const std::string &statusString);
private:
LLVoiceVersionInfo mVoiceVersion;
// Coroutine support methods
@ -671,21 +674,21 @@ private:
// The larger it is the greater is possibility there is a problem with connection to voice server.
// Introduced while fixing EXT-4313.
int mSpatialJoiningNum;
static void idle(void *user_data);
LLHost mDaemonHost;
LLSocket::ptr_t mSocket;
// We should kill the voice daemon in case of connection alert
// We should kill the voice daemon in case of connection alert
bool mTerminateDaemon;
friend class LLVivoxProtocolParser;
std::string mAccountName;
std::string mAccountPassword;
std::string mAccountDisplayName;
bool mTuningMode;
float mTuningEnergy;
std::string mTuningAudioFile;
@ -695,14 +698,13 @@ private:
bool mTuningSpeakerVolumeDirty;
bool mDevicesListUpdated; // set to true when the device list has been updated
// and false when the panelvoicedevicesettings has queried for an update status.
std::string mSpatialSessionURI;
std::string mSpatialSessionCredentials;
std::string mMainSessionGroupHandle; // handle of the "main" session group.
std::string mChannelName; // Name of the channel to be looked up
bool mAreaVoiceDisabled;
std::string mChannelName; // Name of the channel to be looked up
sessionStatePtr_t mAudioSession; // Session state for the current audio session
bool mAudioSessionChanged; // set to true when the above pointer gets changed, so observers can be notified.
@ -710,27 +712,27 @@ private:
S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings
std::string mCurrentRegionName; // Used to detect parcel boundary crossings
bool mConnectorEstablished; // set by "Create Connector" response
bool mAccountLoggedIn; // set by login message
bool mAccountLoggedIn; // set by login message
int mNumberOfAliases;
U32 mCommandCookie;
std::string mVoiceAccountServerURI;
std::string mVoiceSIPURIHostName;
int mLoginRetryCount;
sessionMap mSessionsByHandle; // Active sessions, indexed by session handle. Sessions which are being initiated may not be in this map.
#if 0
sessionSet mSessions; // All sessions, not indexed. This is the canonical session list.
#endif
bool mBuddyListMapPopulated;
bool mBlockRulesListReceived;
bool mAutoAcceptRulesListReceived;
buddyListMap mBuddyListMap;
LLVoiceDeviceList mCaptureDevices;
LLVoiceDeviceList mRenderDevices;
@ -741,32 +743,30 @@ private:
bool mIsInitialized;
bool mShutdownComplete;
bool checkParcelChanged(bool update = false);
bool switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
void joinSession(const sessionStatePtr_t &session);
std::string nameFromAvatar(LLVOAvatar *avatar);
std::string nameFromID(const LLUUID &id);
bool IDFromName(const std::string name, LLUUID &uuid);
std::string displayNameFromAvatar(LLVOAvatar *avatar);
std::string sipURIFromAvatar(LLVOAvatar *avatar);
std::string sipURIFromName(std::string &name);
// Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
std::string nameFromsipURI(const std::string &uri);
std::string nameFromsipURI(const std::string &uri);
bool inSpatialChannel(void);
std::string getAudioSessionURI();
LLSD getAudioSessionChannelInfo();
std::string getAudioSessionHandle();
void setHidden(bool hidden) override; //virtual
void sendPositionAndVolumeUpdate(void);
void sendCaptureAndRenderDevices();
void buildSetCaptureDevice(std::ostringstream &stream);
void buildSetRenderDevice(std::ostringstream &stream);
void sendFriendsListUpdates();
@ -777,9 +777,9 @@ private:
#endif
void enforceTether(void);
bool mSpatialCoordsDirty;
LLVector3d mCameraPosition;
LLVector3d mCameraRequestedPosition;
LLVector3 mCameraVelocity;
@ -788,14 +788,14 @@ private:
LLVector3d mAvatarPosition;
LLVector3 mAvatarVelocity;
LLQuaternion mAvatarRot;
bool mMuteMic;
bool mMuteMicDirty;
bool mHidden; //Set to true during teleport to hide the agent's position.
// Set to true when the friends list is known to have changed.
bool mFriendsListDirty;
enum
{
earLocCamera = 0, // ear at camera
@ -803,22 +803,21 @@ private:
earLocSpeaker, // <FS:Beq> re-add equal voice based loosely on original patch from Tigh MacFanatic
earLocMixed // ear at avatar location/camera direction
};
S32 mEarLocation;
S32 mEarLocation;
bool mSpeakerVolumeDirty;
bool mSpeakerMuteDirty;
int mSpeakerVolume;
int mMicVolume;
bool mMicVolumeDirty;
bool mVoiceEnabled;
bool mProcessChannels;
bool mWriteInProgress;
std::string mWriteString;
size_t mWriteOffset;
BOOL mLipSyncEnabled;
typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
observer_set_t mParticipantObservers;
@ -827,16 +826,13 @@ private:
typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
status_observer_set_t mStatusObservers;
void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
typedef std::set<LLFriendObserver*> friend_observer_set_t;
friend_observer_set_t mFriendObservers;
void notifyFriendObservers();
// <FS:Ansariel> Add callback for user volume change
user_voice_volume_change_callback_t mUserVolumeUpdateSignal;
// Voice Fonts
void expireVoiceFonts();
@ -937,7 +933,7 @@ private:
};
/**
/**
* @class LLVivoxProtocolParser
* @brief This class helps construct new LLIOPipe specializations
* @see LLIOPipe
@ -950,12 +946,12 @@ class LLVivoxProtocolParser : public LLIOPipe
public:
LLVivoxProtocolParser();
virtual ~LLVivoxProtocolParser();
protected:
/* @name LLIOPipe virtual implementations
*/
//@{
/**
/**
* @brief Process the data in buffer
*/
virtual EStatus process_impl(
@ -965,16 +961,16 @@ protected:
LLSD& context,
LLPumpIO* pump);
//@}
std::string mInput;
// Expat control members
XML_Parser parser;
int responseDepth;
bool ignoringTags;
bool isEvent;
int ignoreDepth;
// Members for processing responses. The values are transient and only valid within a call to processResponse().
int returnCode;
int statusCode;
@ -989,7 +985,7 @@ protected:
std::string sessionGroupHandle;
std::string alias;
std::string applicationString;
// Members for processing events. The values are transient and only valid within a call to processResponse().
std::string eventTypeString;
int state;
@ -1028,19 +1024,19 @@ protected:
S32 fontType;
S32 fontStatus;
std::string mediaCompletionType;
// Members for processing text between tags
std::string textBuffer;
bool accumulateText;
void reset();
void processResponse(std::string tag);
static void XMLCALL ExpatStartTag(void *data, const char *el, const char **attr);
static void XMLCALL ExpatEndTag(void *data, const char *el);
static void XMLCALL ExpatCharHandler(void *data, const XML_Char *s, int len);
void StartTag(const char *tag, const char **attr);
void EndTag(const char *tag);
void CharData(const char *buffer, int length);
@ -1072,7 +1068,7 @@ class LLVoiceVivoxStats : public LLSingleton<LLVoiceVivoxStats>
LLSINGLETON(LLVoiceVivoxStats);
LOG_CLASS(LLVoiceVivoxStats);
virtual ~LLVoiceVivoxStats();
private:
F64SecondsImplicit mStartTime;
@ -1080,7 +1076,7 @@ class LLVoiceVivoxStats : public LLSingleton<LLVoiceVivoxStats>
F64 mConnectTime;
U32 mConnectAttempts;
F64 mProvisionTime;
U32 mProvisionAttempts;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,751 @@
/**
* @file llvoicewebrtc.h
* @brief Declaration of LLWebRTCVoiceClient class which is the interface to the voice client process.
*
* $LicenseInfo:firstyear=2001&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 LL_VOICE_WEBRTC_H
#define LL_VOICE_WEBRTC_H
class LLWebRTCProtocolParser;
#include "lliopipe.h"
#include "llpumpio.h"
#include "llchainio.h"
#include "lliosocket.h"
#include "v3math.h"
#include "llframetimer.h"
#include "llviewerregion.h"
#include "llcallingcard.h" // for LLFriendObserver
#include "lleventcoro.h"
#include "llcoros.h"
#include "llparcel.h"
#include "llmutelist.h"
#include <queue>
#include "json/reader.h"
#ifdef LL_USESYSTEMLIBS
# include "expat.h"
#else
# include "expat/expat.h"
#endif
#include "llvoiceclient.h"
// WebRTC Includes
#include <llwebrtc.h>
class LLAvatarName;
class LLVoiceWebRTCConnection;
typedef boost::shared_ptr<LLVoiceWebRTCConnection> connectionPtr_t;
extern const std::string WEBRTC_VOICE_SERVER_TYPE;
class LLWebRTCVoiceClient : public LLSingleton<LLWebRTCVoiceClient>,
virtual public LLVoiceModuleInterface,
public llwebrtc::LLWebRTCDevicesObserver,
public LLMuteListObserver
{
LLSINGLETON_C11(LLWebRTCVoiceClient);
LOG_CLASS(LLWebRTCVoiceClient);
virtual ~LLWebRTCVoiceClient();
public:
/// @name LLVoiceModuleInterface virtual implementations
/// @see LLVoiceModuleInterface
//@{
void init(LLPumpIO *pump) override; // Call this once at application startup (creates connector)
void terminate() override; // Call this to clean up during shutdown
static bool isShuttingDown() { return sShuttingDown; }
const LLVoiceVersionInfo& getVersion() override;
void updateSettings() override; // call after loading settings and whenever they change
// Returns true if WebRTC has successfully logged in and is not in error state
bool isVoiceWorking() const override;
std::string sipURIFromID(const LLUUID &id) override;
/////////////////////
/// @name Tuning
//@{
void tuningStart() override;
void tuningStop() override;
bool inTuningMode() override;
void tuningSetMicVolume(float volume) override;
void tuningSetSpeakerVolume(float volume) override;
float tuningGetEnergy(void) override;
//@}
/////////////////////
/// @name Devices
//@{
// This returns true when it's safe to bring up the "device settings" dialog in the prefs.
bool deviceSettingsAvailable() override;
bool deviceSettingsUpdated() override; //return if the list has been updated and never fetched, only to be called from the voicepanel.
// Requery the WebRTC daemon for the current list of input/output devices.
// If you pass true for clearCurrentList, deviceSettingsAvailable() will be false until the query has completed
// (use this if you want to know when it's done).
// If you pass false, you'll have no way to know when the query finishes, but the device lists will not appear empty in the interim.
void refreshDeviceLists(bool clearCurrentList = true) override;
void setCaptureDevice(const std::string& name) override;
void setRenderDevice(const std::string& name) override;
LLVoiceDeviceList& getCaptureDevices() override;
LLVoiceDeviceList& getRenderDevices() override;
//@}
void getParticipantList(std::set<LLUUID> &participants) override;
bool isParticipant(const LLUUID& speaker_id) override;
// Send a text message to the specified user, initiating the session if necessary.
// virtual BOOL sendTextMessage(const LLUUID& participant_id, const std::string& message) const {return false;};
// Returns true if calling back the session URI after the session has closed is possible.
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
BOOL isSessionCallBackPossible(const LLUUID &session_id) override;
// WebRTC doesn't preclude text im
BOOL isSessionTextIMPossible(const LLUUID &session_id) override { return TRUE; }
////////////////////////////
/// @name Channel stuff
//@{
// returns true iff the user is currently in a proximal (local spatial) channel.
// Note that gestures should only fire if this returns true.
bool inProximalChannel() override;
void setNonSpatialChannel(const LLSD& channelInfo, bool notify_on_first_join, bool hangup_on_last_leave) override
{
startAdHocSession(channelInfo, notify_on_first_join, hangup_on_last_leave);
}
bool setSpatialChannel(const LLSD &channelInfo) override
{
// we don't really have credentials for a spatial channel in webrtc,
// it's all handled by the sim.
return true;
}
void leaveNonSpatialChannel() override;
void processChannels(bool process) override;
void leaveChannel(bool stopTalking);
bool isCurrentChannel(const LLSD &channelInfo) override;
bool compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2) override;
//@}
LLVoiceP2POutgoingCallInterface *getOutgoingCallInterface() override { return nullptr; }
LLVoiceP2PIncomingCallInterfacePtr getIncomingCallInterface(const LLSD &voice_call_info) override { return nullptr; }
/////////////////////////
/// @name Volume/gain
//@{
void setVoiceVolume(F32 volume) override;
void setMicGain(F32 volume) override;
//@}
/////////////////////////
/// @name enable disable voice and features
//@{
void setVoiceEnabled(bool enabled) override;
void setMuteMic(bool muted) override; // Set the mute state of the local mic.
//@}
//////////////////////////
/// @name nearby speaker accessors
std::string getDisplayName(const LLUUID& id) override;
BOOL isParticipantAvatar(const LLUUID &id) override;
BOOL getIsSpeaking(const LLUUID& id) override;
BOOL getIsModeratorMuted(const LLUUID& id) override;
F32 getCurrentPower(const LLUUID& id) override; // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
F32 getUserVolume(const LLUUID& id) override;
void setUserVolume(const LLUUID& id, F32 volume) override; // set's volume for specified agent, from 0-1 (where .5 is nominal)
//@}
//////////////////
/// @name LLMuteListObserver
//@{
void onChange() override;
void onChangeDetailed(const LLMute& ) override;
//@}
// authorize the user
void userAuthorized(const std::string &user_id, const LLUUID &agentID) override {};
void OnConnectionEstablished(const std::string& channelID, const LLUUID& regionID);
void OnConnectionShutDown(const std::string &channelID, const LLUUID &regionID);
void OnConnectionFailure(const std::string &channelID, const LLUUID& regionID);
void sendPositionUpdate(bool force);
void updateOwnVolume();
//////////////////////////////
/// @name Status notification
//@{
void addObserver(LLVoiceClientStatusObserver* observer) override;
void removeObserver(LLVoiceClientStatusObserver* observer) override;
void addObserver(LLFriendObserver* observer) override;
void removeObserver(LLFriendObserver* observer) override;
void addObserver(LLVoiceClientParticipantObserver* observer) override;
void removeObserver(LLVoiceClientParticipantObserver* observer) override;
//@}
//////////////////////////////
/// @name Devices change notification
// LLWebRTCDevicesObserver
//@{
void OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices,
const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices) override;
//@}
struct participantState
{
public:
participantState(const LLUUID& agent_id);
bool isAvatar();
std::string mURI;
LLUUID mAvatarID;
std::string mDisplayName;
LLFrameTimer mSpeakingTimeout;
F32 mLevel; // the current audio level of the participant
F32 mVolume; // the gain applied to the participant
bool mIsSpeaking;
bool mIsModeratorMuted;
};
typedef boost::shared_ptr<participantState> participantStatePtr_t;
participantStatePtr_t findParticipantByID(const std::string &channelID, const LLUUID &id);
participantStatePtr_t addParticipantByID(const std::string& channelID, const LLUUID &id);
void removeParticipantByID(const std::string& channelID, const LLUUID &id);
protected:
typedef std::map<const LLUUID, participantStatePtr_t> participantUUIDMap;
class sessionState
{
public:
typedef boost::shared_ptr<sessionState> ptr_t;
typedef boost::weak_ptr<sessionState> wptr_t;
typedef boost::function<void(const ptr_t &)> sessionFunc_t;
static void addSession(const std::string &channelID, ptr_t& session);
virtual ~sessionState();
participantStatePtr_t addParticipant(const LLUUID& agent_id);
void removeParticipant(const participantStatePtr_t &participant);
void removeAllParticipants();
participantStatePtr_t findParticipantByID(const LLUUID& id);
static ptr_t matchSessionByChannelID(const std::string& channel_id);
void shutdownAllConnections();
void revive();
static void processSessionStates();
virtual bool processConnectionStates();
virtual void sendData(const std::string &data);
void setMuteMic(bool muted);
void setMicGain(F32 volume);
void setSpeakerVolume(F32 volume);
void setUserVolume(const LLUUID& id, F32 volume);
void setUserMute(const LLUUID& id, bool mute);
static void for_each(sessionFunc_t func);
static void reapEmptySessions();
bool isEmpty() { return mWebRTCConnections.empty(); }
virtual bool isSpatial() = 0;
virtual bool isEstate() = 0;
virtual bool isCallbackPossible() = 0;
std::string mHandle;
std::string mChannelID;
std::string mName;
bool mMuted; // this session is muted.
F32 mMicGain; // gain for this session.
F32 mSpeakerVolume; // volume for this session.
bool mShuttingDown;
participantUUIDMap mParticipantsByUUID;
static bool hasSession(const std::string &sessionID)
{ return mSessions.find(sessionID) != mSessions.end(); }
bool mHangupOnLastLeave; // notify observers after the session becomes empty.
bool mNotifyOnFirstJoin; // notify observers when the first peer joins.
protected:
sessionState();
std::list<connectionPtr_t> mWebRTCConnections;
private:
static std::map<std::string, ptr_t> mSessions; // canonical list of outstanding sessions.
static void for_eachPredicate(const std::pair<std::string,
LLWebRTCVoiceClient::sessionState::wptr_t> &a,
sessionFunc_t func);
};
typedef boost::shared_ptr<sessionState> sessionStatePtr_t;
typedef std::map<std::string, sessionStatePtr_t> sessionMap;
class estateSessionState : public sessionState
{
public:
estateSessionState();
bool processConnectionStates() override;
bool isSpatial() override { return true; }
bool isEstate() override { return true; }
bool isCallbackPossible() override { return false; }
};
class parcelSessionState : public sessionState
{
public:
parcelSessionState(const std::string& channelID, S32 parcel_local_id);
bool isSpatial() override { return true; }
bool isEstate() override { return false; }
bool isCallbackPossible() override { return false; }
};
class adhocSessionState : public sessionState
{
public:
adhocSessionState(const std::string &channelID,
const std::string& credentials,
bool notify_on_first_join,
bool hangup_on_last_leave);
bool isSpatial() override { return false; }
bool isEstate() override { return false; }
// only p2p-type adhoc sessions allow callback
bool isCallbackPossible() override { return mNotifyOnFirstJoin && mHangupOnLastLeave; }
// don't send spatial data to adhoc sessions.
void sendData(const std::string &data) override { }
protected:
std::string mCredentials;
};
///////////////////////////////////////////////////////
// Private Member Functions
//////////////////////////////////////////////////////
static void predSendData(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const std::string& spatial_data);
static void predUpdateOwnVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 audio_level);
static void predSetMuteMic(const LLWebRTCVoiceClient::sessionStatePtr_t &session, bool mute);
static void predSetMicGain(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume);
static void predSetSpeakerVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume);
static void predShutdownSession(const LLWebRTCVoiceClient::sessionStatePtr_t &session);
static void predSetUserMute(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const LLUUID& id, bool mute);
static void predSetUserVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const LLUUID& id, F32 volume);
//----------------------------------
// devices
void clearCaptureDevices();
void addCaptureDevice(const LLVoiceDevice& device);
void clearRenderDevices();
void addRenderDevice(const LLVoiceDevice& device);
void setDevicesListUpdated(bool state);
/////////////////////////////
// Sending updates of current state
void updatePosition(void);
void setListenerPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot);
void setAvatarPosition(const LLVector3d &position, const LLVector3 &velocity, const LLQuaternion &rot);
LLVector3d getListenerPosition() { return mListenerPosition; }
LLVector3d getSpeakerPosition() { return mAvatarPosition; }
void setEarLocation(S32 loc);
/////////////////////////////
// Accessors for data related to nearby speakers
/////////////////////////////
sessionStatePtr_t findP2PSession(const LLUUID &agent_id);
sessionStatePtr_t addSession(const std::string &channel_id, sessionState::ptr_t session);
void deleteSession(const sessionStatePtr_t &session);
// Does the actual work to get out of the audio session
void leaveAudioSession();
friend class LLWebRTCVoiceClientCapResponder;
void lookupName(const LLUUID &id);
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
void avatarNameResolved(const LLUUID &id, const std::string &name);
static void predAvatarNameResolution(const LLWebRTCVoiceClient::sessionStatePtr_t &session, LLUUID id, std::string name);
boost::signals2::connection mAvatarNameCacheConnection;
private:
// helper function to retrieve the audio level
// Used in multiple places.
float getAudioLevel();
// Coroutine support methods
//---
void voiceConnectionCoro();
//---
/// Clean up objects created during a voice session.
void cleanUp();
bool mTuningMode;
F32 mTuningMicGain;
int mTuningSpeakerVolume;
bool mDevicesListUpdated; // set to true when the device list has been updated
// and false when the panelvoicedevicesettings has queried for an update status.
std::string mSpatialSessionCredentials;
std::string mMainSessionGroupHandle; // handle of the "main" session group.
sessionStatePtr_t mSession; // Session state for the current session
sessionStatePtr_t mNextSession; // Session state for the session we're trying to join
llwebrtc::LLWebRTCDeviceInterface *mWebRTCDeviceInterface;
LLVoiceDeviceList mCaptureDevices;
LLVoiceDeviceList mRenderDevices;
bool startEstateSession();
bool startParcelSession(const std::string& channelID, S32 parcelID);
bool startAdHocSession(const LLSD &channelInfo, bool notify_on_first_join, bool hangup_on_last_leave);
bool inSpatialChannel();
bool inOrJoiningChannel(const std::string &channelID);
bool inEstateChannel();
LLSD getAudioSessionChannelInfo();
void setHidden(bool hidden) override; //virtual
void enforceTether();
void updateNeighboringRegions();
std::set<LLUUID> getNeighboringRegions() { return mNeighboringRegions; }
LLVoiceVersionInfo mVoiceVersion;
bool mSpatialCoordsDirty;
LLVector3d mListenerPosition;
LLVector3d mListenerRequestedPosition;
LLVector3 mListenerVelocity;
LLQuaternion mListenerRot;
LLVector3d mAvatarPosition;
LLVector3 mAvatarVelocity;
LLQuaternion mAvatarRot;
std::set<LLUUID> mNeighboringRegions; // includes current region
bool mMuteMic;
bool mHidden; //Set to true during teleport to hide the agent's position.
enum
{
earLocCamera = 0, // ear at camera
earLocAvatar, // ear at avatar
earLocMixed // ear at avatar location/camera direction
};
S32 mEarLocation;
float mSpeakerVolume;
F32 mMicGain;
bool mVoiceEnabled;
bool mProcessChannels;
typedef std::set<LLVoiceClientParticipantObserver*> observer_set_t;
observer_set_t mParticipantObservers;
void notifyParticipantObservers();
typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
status_observer_set_t mStatusObservers;
void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
bool mIsInTuningMode;
bool mIsProcessingChannels;
bool mIsCoroutineActive;
// These variables can last longer than WebRTC in coroutines so we need them as static
static bool sShuttingDown;
LLEventMailDrop mWebRTCPump;
};
class LLVoiceWebRTCStats : public LLSingleton<LLVoiceWebRTCStats>
{
LLSINGLETON(LLVoiceWebRTCStats);
LOG_CLASS(LLVoiceWebRTCStats);
virtual ~LLVoiceWebRTCStats();
private:
F64SecondsImplicit mStartTime;
U32 mConnectCycles;
F64 mConnectTime;
U32 mConnectAttempts;
F64 mProvisionTime;
U32 mProvisionAttempts;
F64 mEstablishTime;
U32 mEstablishAttempts;
public:
void reset();
void connectionAttemptStart();
void connectionAttemptEnd(bool success);
void provisionAttemptStart();
void provisionAttemptEnd(bool success);
void establishAttemptStart();
void establishAttemptEnd(bool success);
LLSD read();
};
class LLVoiceWebRTCConnection :
public llwebrtc::LLWebRTCSignalingObserver,
public llwebrtc::LLWebRTCDataObserver
{
public:
LLVoiceWebRTCConnection(const LLUUID &regionID, const std::string &channelID);
virtual ~LLVoiceWebRTCConnection() = 0;
//////////////////////////////
/// @name Signaling notification
// LLWebRTCSignalingObserver
//@{
void OnIceGatheringState(EIceGatheringState state) override;
void OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate &candidate) override;
void OnOfferAvailable(const std::string &sdp) override;
void OnRenegotiationNeeded() override;
void OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface *audio_interface) override;
void OnPeerConnectionShutdown() override;
//@}
/////////////////////////
/// @name Data Notification
/// LLWebRTCDataObserver
//@{
void OnDataReceived(const std::string &data, bool binary) override;
void OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) override;
//@}
void sendJoin();
void sendData(const std::string &data);
virtual void processIceUpdates();
virtual void onIceUpdateComplete(bool ice_completed, const LLSD &result);
virtual void onIceUpdateError(int retries, std::string url, LLSD body, bool ice_completed, const LLSD &result);
virtual void setMuteMic(bool muted);
virtual void setMicGain(F32 volume);
virtual void setSpeakerVolume(F32 volume);
void setUserVolume(const LLUUID& id, F32 volume);
void setUserMute(const LLUUID& id, bool mute);
bool connectionStateMachine();
virtual bool isSpatial() = 0;
LLUUID getRegionID() { return mRegionID; }
void shutDown()
{
LLMutexLock lock(&mVoiceStateMutex);
mShutDown = true;
}
void OnVoiceConnectionRequestSuccess(const LLSD &body);
void OnVoiceConnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
protected:
typedef enum e_voice_connection_state
{
VOICE_STATE_ERROR = 0x0,
VOICE_STATE_START_SESSION = 0x1,
VOICE_STATE_WAIT_FOR_SESSION_START = 0x2,
VOICE_STATE_REQUEST_CONNECTION = 0x4,
VOICE_STATE_CONNECTION_WAIT = 0x8,
VOICE_STATE_SESSION_ESTABLISHED = 0x10,
VOICE_STATE_WAIT_FOR_DATA_CHANNEL = 0x20,
VOICE_STATE_SESSION_UP = 0x40,
VOICE_STATE_SESSION_RETRY = 0x80,
VOICE_STATE_DISCONNECT = 0x100,
VOICE_STATE_WAIT_FOR_EXIT = 0x200,
VOICE_STATE_SESSION_EXIT = 0x400,
VOICE_STATE_SESSION_STOPPING = 0x780
} EVoiceConnectionState;
EVoiceConnectionState mVoiceConnectionState;
LLMutex mVoiceStateMutex;
void setVoiceConnectionState(EVoiceConnectionState new_voice_connection_state)
{
LLMutexLock lock(&mVoiceStateMutex);
if (new_voice_connection_state & VOICE_STATE_SESSION_STOPPING)
{
// the new state is shutdown or restart.
mVoiceConnectionState = new_voice_connection_state;
return;
}
if (mVoiceConnectionState & VOICE_STATE_SESSION_STOPPING)
{
// we're currently shutting down or restarting, so ignore any
// state changes.
return;
}
mVoiceConnectionState = new_voice_connection_state;
}
EVoiceConnectionState getVoiceConnectionState()
{
if (mVoiceStateMutex.isLocked())
{
LL_WARNS("Voice") << "LOCKED." << LL_ENDL;
}
LLMutexLock lock(&mVoiceStateMutex);
return mVoiceConnectionState;
}
virtual bool requestVoiceConnection() = 0;
bool breakVoiceConnection(bool wait);
void OnVoiceDisconnectionRequestSuccess(const LLSD &body);
void OnVoiceDisconnectionRequestFailure(std::string url, int retries, LLSD body, const LLSD &result);
LLUUID mRegionID;
LLUUID mViewerSession;
std::string mChannelID;
std::string mChannelSDP;
std::string mRemoteChannelSDP;
bool mMuted;
F32 mMicGain;
F32 mSpeakerVolume;
bool mShutDown;
S32 mOutstandingRequests;
S32 mRetryWaitPeriod; // number of UPDATE_THROTTLE_SECONDS we've
// waited since our last attempt to connect.
F32 mRetryWaitSecs; // number of seconds to wait before next retry
std::vector<llwebrtc::LLWebRTCIceCandidate> mIceCandidates;
bool mIceCompleted;
bool mTrickling;
llwebrtc::LLWebRTCPeerConnectionInterface *mWebRTCPeerConnectionInterface;
llwebrtc::LLWebRTCAudioInterface *mWebRTCAudioInterface;
llwebrtc::LLWebRTCDataInterface *mWebRTCDataInterface;
};
class LLVoiceWebRTCSpatialConnection :
public LLVoiceWebRTCConnection
{
public:
LLVoiceWebRTCSpatialConnection(const LLUUID &regionID, S32 parcelLocalID, const std::string &channelID);
virtual ~LLVoiceWebRTCSpatialConnection();
void setMuteMic(bool muted) override;
bool isSpatial() override { return true; }
protected:
bool requestVoiceConnection() override;
S32 mParcelLocalID;
};
class LLVoiceWebRTCAdHocConnection : public LLVoiceWebRTCConnection
{
public:
LLVoiceWebRTCAdHocConnection(const LLUUID &regionID, const std::string &channelID, const std::string& credentials);
virtual ~LLVoiceWebRTCAdHocConnection();
bool isSpatial() override { return false; }
protected:
bool requestVoiceConnection() override;
std::string mCredentials;
};
#define VOICE_ELAPSED LLVoiceTimer(__FUNCTION__);
#endif //LL_WebRTC_VOICE_CLIENT_H

View File

@ -655,6 +655,12 @@ class Windows_x86_64_Manifest(ViewerManifest):
# Get shared libs from the shared libs staging directory
with self.prefix(src=os.path.join(self.args['build'], os.pardir,
'sharedlibs', self.args['buildtype'])):
# WebRTC libraries
for libfile in (
'llwebrtc.dll',
):
self.path(libfile)
# Mesh 3rd party libs needed for auto LOD and collada reading
try:
@ -1516,6 +1522,20 @@ class Darwin_x86_64_Manifest(ViewerManifest):
print("Skipping %s" % dst)
return added
# WebRTC libraries
with self.prefix(src=os.path.join(self.args['build'], os.pardir,
'sharedlibs', self.args['buildtype'], 'Resources')):
for libfile in (
'libllwebrtc.dylib',
):
self.path(libfile)
oldpath = os.path.join("@rpath", libfile)
self.run_command(
['install_name_tool', '-change', oldpath,
'@executable_path/../Resources/%s' % libfile,
executable])
# dylibs is a list of all the .dylib files we expect to need
# in our bundled sub-apps. For each of these we'll create a
# symlink from sub-app/Contents/Resources to the real .dylib.