Merge branch 'webrtc-voice' of https://github.com/secondlife/viewer
# 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.sha1master
commit
5e75273b49
|
|
@ -76,3 +76,6 @@ c/cpp:
|
|||
- '**/*.i'
|
||||
- '**/*.inl'
|
||||
- '**/*.y'
|
||||
|
||||
'team:viewer':
|
||||
- '*'
|
||||
|
|
|
|||
1521
autobuild.xml
1521
autobuild.xml
File diff suppressed because it is too large
Load Diff
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ set(cmake_SOURCE_FILES
|
|||
ViewerMiscLibs.cmake
|
||||
VisualLeakDetector.cmake
|
||||
LibVLCPlugin.cmake
|
||||
WebRTC.cmake
|
||||
XmlRpcEpi.cmake
|
||||
xxHash.cmake
|
||||
ZLIBNG.cmake
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#ifndef LL_LLAPPVIEWER_H
|
||||
#define LL_LLAPPVIEWER_H
|
||||
|
||||
#include "llapp.h"
|
||||
#include "llallocator.h"
|
||||
#include "llapr.h"
|
||||
#include "llcontrol.h"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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") )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 = "";
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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 ¬ificationType);
|
||||
|
||||
|
||||
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
|
|
@ -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 ®ionID);
|
||||
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 ®ionID, 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 ®ionID, 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 ®ionID, 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
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue