[Voice Update] Small sync, less warning spam is likely
Should fix group chats sometimes not showing anyone. (Seemed to for me! ^*^)
This commit is contained in:
@@ -4168,6 +4168,28 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>ChatLoadGroupMaxMembers</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Max number of active members we'll show up for an unresponsive group</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<real>100</real>
|
||||
</map>
|
||||
<key>ChatLoadGroupTimeout</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Time we give the server to send group participants before we hit the server for group info (seconds)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>10.0</real>
|
||||
</map>
|
||||
<key>ChatOnlineNotification</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llimpanel.h" // For LLFloaterIMPanel
|
||||
#include "llimview.h"
|
||||
#include "llgroupmgr.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llui.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
@@ -61,8 +62,7 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy
|
||||
mModeratorMutedVoice(FALSE),
|
||||
mModeratorMutedText(FALSE)
|
||||
{
|
||||
// Make sure we also get the display name if SLIM or some other external voice client is used and not whatever is provided.
|
||||
if ((name.empty() && type == SPEAKER_AGENT) || type == SPEAKER_EXTERNAL)
|
||||
if (name.empty() && type == SPEAKER_AGENT)
|
||||
{
|
||||
lookupName();
|
||||
}
|
||||
@@ -100,6 +100,19 @@ bool LLSpeaker::isInVoiceChannel()
|
||||
return mStatus <= LLSpeaker::STATUS_VOICE_ACTIVE || mStatus == LLSpeaker::STATUS_MUTED;
|
||||
}
|
||||
|
||||
LLSpeakerUpdateSpeakerEvent::LLSpeakerUpdateSpeakerEvent(LLSpeaker* source)
|
||||
: LLEvent(source, "Speaker update speaker event"),
|
||||
mSpeakerID (source->mID)
|
||||
{
|
||||
}
|
||||
|
||||
LLSD LLSpeakerUpdateSpeakerEvent::getValue()
|
||||
{
|
||||
LLSD ret;
|
||||
ret["id"] = mSpeakerID;
|
||||
return ret;
|
||||
}
|
||||
|
||||
LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source)
|
||||
: LLEvent(source, "Speaker add moderator event"),
|
||||
mSpeakerID (source->mID),
|
||||
@@ -257,6 +270,11 @@ bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSpeakersDelayActionsStorage::isTimerStarted(const LLUUID& speaker_id)
|
||||
{
|
||||
return (mActionTimersMap.size() > 0) && (mActionTimersMap.find(speaker_id) != mActionTimersMap.end());
|
||||
}
|
||||
|
||||
//
|
||||
// ModerationResponder
|
||||
//
|
||||
@@ -269,9 +287,9 @@ public:
|
||||
mSessionID = session_id;
|
||||
}
|
||||
|
||||
/*virtual*/ void error(U32 status, const std::string& reason)
|
||||
virtual void error(U32 status, const std::string& reason)
|
||||
{
|
||||
llwarns << "ModerationResponder error [status:" << status << "]: " << reason << llendl;
|
||||
llwarns << status << ": " << reason << llendl;
|
||||
|
||||
if ( gIMMgr )
|
||||
{
|
||||
@@ -308,8 +326,10 @@ private:
|
||||
LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
|
||||
mVoiceChannel(channelp),
|
||||
mVoiceModerated(false),
|
||||
mModerateModeHandledFirstTime(false)
|
||||
mModerateModeHandledFirstTime(false),
|
||||
mSpeakerListUpdated(false)
|
||||
{
|
||||
mGetListTime.reset();
|
||||
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
|
||||
|
||||
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
|
||||
@@ -322,7 +342,8 @@ LLSpeakerMgr::~LLSpeakerMgr()
|
||||
|
||||
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
|
||||
{
|
||||
if (id.isNull())
|
||||
LLUUID session_id = getSessionID();
|
||||
if (id.isNull() || (id == session_id))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -434,6 +455,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
||||
{
|
||||
speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
|
||||
speakerp->mHasSpoken = TRUE;
|
||||
fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker");
|
||||
}
|
||||
speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
|
||||
// interpolate between active color and full speaking color based on power of speech output
|
||||
@@ -522,6 +544,81 @@ void LLSpeakerMgr::updateSpeakerList()
|
||||
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not, check if the list is empty, except if it's Nearby Chat (session_id NULL).
|
||||
LLUUID session_id = getSessionID();
|
||||
if (!session_id.isNull() && !mSpeakerListUpdated)
|
||||
{
|
||||
// If the list is empty, we update it with whatever we have locally so that it doesn't stay empty too long.
|
||||
// *TODO: Fix the server side code that sometimes forgets to send back the list of participants after a chat started.
|
||||
// (IOW, fix why we get no ChatterBoxSessionAgentListUpdates message after the initial ChatterBoxSessionStartReply)
|
||||
/* Singu TODO: LLIMModel::LLIMSession
|
||||
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
|
||||
if (session->isGroupSessionType() && (mSpeakers.size() <= 1))
|
||||
*/
|
||||
LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id);
|
||||
if (floater && floater->getSessionType() == LLFloaterIMPanel::GROUP_SESSION && (mSpeakers.size() <= 1))
|
||||
{
|
||||
const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout");
|
||||
// For groups, we need to hit the group manager.
|
||||
// Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail.
|
||||
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id);
|
||||
if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout))
|
||||
{
|
||||
// Request the data the first time around
|
||||
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id);
|
||||
}
|
||||
else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
|
||||
{
|
||||
// Add group members when we get the complete list (note: can take a while before we get that list)
|
||||
LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin();
|
||||
const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers");
|
||||
S32 updated = 0;
|
||||
while (member_it != gdatap->mMembers.end())
|
||||
{
|
||||
LLGroupMemberData* member = member_it->second;
|
||||
LLUUID id = member_it->first;
|
||||
// Add only members who are online and not already in the list
|
||||
if ((member->getOnlineStatus() == "Online") && (mSpeakers.find(id) == mSpeakers.end()))
|
||||
{
|
||||
LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
|
||||
speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR);
|
||||
updated++;
|
||||
}
|
||||
++member_it;
|
||||
// Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop
|
||||
// *TODO : solve the perf issue of having several hundreds of widgets in the conversation list
|
||||
if (updated >= load_group_max_members)
|
||||
break;
|
||||
}
|
||||
mSpeakerListUpdated = true;
|
||||
}
|
||||
}
|
||||
/* Singu TODO: LLIMModel::LLIMSession
|
||||
else if (mSpeakers.size() == 0)
|
||||
{
|
||||
// For all other session type (ad-hoc, P2P, avaline), we use the initial participants targets list
|
||||
for (uuid_vec_t::iterator it = session->mInitialTargetIDs.begin();it!=session->mInitialTargetIDs.end();++it)
|
||||
{
|
||||
// Add buddies if they are on line, add any other avatar.
|
||||
if (!LLAvatarTracker::instance().isBuddy(*it) || LLAvatarTracker::instance().isBuddyOnline(*it))
|
||||
{
|
||||
setSpeaker(*it, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
|
||||
}
|
||||
}
|
||||
mSpeakerListUpdated = true;
|
||||
}
|
||||
*/
|
||||
else
|
||||
{
|
||||
// The list has been updated the normal way (i.e. by a ChatterBoxSessionAgentListUpdates received from the server)
|
||||
mSpeakerListUpdated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Always add the current agent (it has to be there...). Will do nothing if already there.
|
||||
setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
|
||||
}
|
||||
|
||||
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
|
||||
@@ -586,6 +683,10 @@ const LLUUID LLSpeakerMgr::getSessionID()
|
||||
return mVoiceChannel->getSessionID();
|
||||
}
|
||||
|
||||
bool LLSpeakerMgr::isSpeakerToBeRemoved(const LLUUID& speaker_id)
|
||||
{
|
||||
return mSpeakerDelayRemover && mSpeakerDelayRemover->isTimerStarted(speaker_id);
|
||||
}
|
||||
|
||||
void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing)
|
||||
{
|
||||
@@ -604,6 +705,7 @@ void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
|
||||
{
|
||||
speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
|
||||
speakerp->mHasSpoken = TRUE;
|
||||
fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -956,7 +1058,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
|
||||
if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
|
||||
{
|
||||
LLVOAvatar* avatarp = gObjectList.findAvatar(speaker_id);
|
||||
if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS_SQUARED)
|
||||
if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS)
|
||||
{
|
||||
setSpeakerNotInChannel(speakerp);
|
||||
}
|
||||
|
||||
@@ -81,6 +81,15 @@ public:
|
||||
BOOL mModeratorMutedText;
|
||||
};
|
||||
|
||||
class LLSpeakerUpdateSpeakerEvent : public LLOldEvents::LLEvent
|
||||
{
|
||||
public:
|
||||
LLSpeakerUpdateSpeakerEvent(LLSpeaker* source);
|
||||
/*virtual*/ LLSD getValue();
|
||||
private:
|
||||
const LLUUID& mSpeakerID;
|
||||
};
|
||||
|
||||
class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent
|
||||
{
|
||||
public:
|
||||
@@ -186,6 +195,8 @@ public:
|
||||
void unsetActionTimer(const LLUUID& speaker_id);
|
||||
|
||||
void removeAllTimers();
|
||||
|
||||
bool isTimerStarted(const LLUUID& speaker_id);
|
||||
private:
|
||||
/**
|
||||
* Callback of the each instance of LLSpeakerActionTimer.
|
||||
@@ -230,6 +241,7 @@ public:
|
||||
void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text);
|
||||
LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
|
||||
const LLUUID getSessionID();
|
||||
bool isSpeakerToBeRemoved(const LLUUID& speaker_id);
|
||||
|
||||
/**
|
||||
* Removes avaline speaker.
|
||||
@@ -253,6 +265,8 @@ protected:
|
||||
|
||||
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
|
||||
speaker_map_t mSpeakers;
|
||||
bool mSpeakerListUpdated;
|
||||
LLTimer mGetListTime;
|
||||
|
||||
speaker_list_t mSpeakersSorted;
|
||||
LLFrameTimer mSpeechTimer;
|
||||
|
||||
@@ -55,8 +55,9 @@ class LLVoiceCallCapResponder : public LLHTTPClient::ResponderWithResult
|
||||
public:
|
||||
LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
|
||||
|
||||
/*virtual*/ void error(U32 status, const std::string& reason); // called with bad status codes
|
||||
/*virtual*/ void result(const LLSD& content);
|
||||
// called with bad status codes
|
||||
virtual void error(U32 status, const std::string& reason);
|
||||
virtual void result(const LLSD& content);
|
||||
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return voiceCallCapResponder_timeout; }
|
||||
/*virtual*/ char const* getName(void) const { return "LLVoiceCallCapResponder"; }
|
||||
|
||||
@@ -412,7 +413,7 @@ void LLVoiceChannel::doSetState(const EState& new_state)
|
||||
mState = new_state;
|
||||
|
||||
if (!mStateChangedCallback.empty())
|
||||
mStateChangedCallback(old_state, mState, mCallDirection, mCallEndedByAgent);
|
||||
mStateChangedCallback(old_state, mState, mCallDirection, mCallEndedByAgent, mSessionID);
|
||||
}
|
||||
|
||||
//static
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
OUTGOING_CALL
|
||||
} EDirection;
|
||||
|
||||
typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction, bool ended_by_agent)> state_changed_signal_t;
|
||||
typedef boost::signals2::signal<void(const EState& old_state, const EState& new_state, const EDirection& direction, bool ended_by_agent, const LLUUID& session_id)> state_changed_signal_t;
|
||||
|
||||
// on current channel changed signal
|
||||
typedef boost::function<void(const LLUUID& session_id)> channel_changed_callback_t;
|
||||
@@ -58,7 +58,6 @@ public:
|
||||
static boost::signals2::connection setCurrentVoiceChannelChangedCallback(channel_changed_callback_t cb, bool at_front = false);
|
||||
|
||||
|
||||
|
||||
LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
|
||||
virtual ~LLVoiceChannel();
|
||||
|
||||
@@ -202,4 +201,3 @@ private:
|
||||
};
|
||||
|
||||
#endif // LL_VOICECHANNEL_H
|
||||
|
||||
|
||||
@@ -112,8 +112,8 @@ LLVoiceClient::LLVoiceClient()
|
||||
:
|
||||
mVoiceModule(NULL),
|
||||
m_servicePump(NULL),
|
||||
mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled")),
|
||||
mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault")),
|
||||
mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled", true)),
|
||||
mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault", "00000000-0000-0000-0000-000000000000")),
|
||||
mPTTDirty(true),
|
||||
mPTT(true),
|
||||
mUsePTT(true),
|
||||
|
||||
@@ -295,6 +295,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
|
||||
mSessionTerminateRequested(false),
|
||||
mRelogRequested(false),
|
||||
mConnected(false),
|
||||
mTerminateDaemon(false),
|
||||
mPump(NULL),
|
||||
mSpatialJoiningNum(0),
|
||||
|
||||
@@ -567,25 +568,25 @@ void LLVivoxVoiceClient::requestVoiceAccountProvision(S32 retries)
|
||||
{
|
||||
LLViewerRegion *region = gAgent.getRegion();
|
||||
|
||||
if ( region && (mVoiceEnabled || !mIsInitialized))
|
||||
// If we've not received the capability yet, return.
|
||||
// the password will remain empty, so we'll remain in
|
||||
// stateIdle
|
||||
if ( region &&
|
||||
region->capabilitiesReceived() &&
|
||||
(mVoiceEnabled || !mIsInitialized))
|
||||
{
|
||||
std::string url =
|
||||
region->getCapability("ProvisionVoiceAccountRequest");
|
||||
|
||||
if ( url.empty() )
|
||||
if ( !url.empty() )
|
||||
{
|
||||
// we've not received the capability yet, so return.
|
||||
// the password will remain empty, so we'll remain in
|
||||
// stateIdle
|
||||
return;
|
||||
LLHTTPClient::post(
|
||||
url,
|
||||
LLSD(),
|
||||
new LLVivoxVoiceAccountProvisionResponder(retries));
|
||||
|
||||
setState(stateConnectorStart);
|
||||
}
|
||||
|
||||
LLHTTPClient::post(
|
||||
url,
|
||||
LLSD(),
|
||||
new LLVivoxVoiceAccountProvisionResponder(retries));
|
||||
|
||||
setState(stateConnectorStart);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -738,7 +739,7 @@ void LLVivoxVoiceClient::stateMachine()
|
||||
setVoiceEnabled(false);
|
||||
}
|
||||
|
||||
if(mVoiceEnabled || !mIsInitialized)
|
||||
if(mVoiceEnabled || (!mIsInitialized && !mTerminateDaemon) )
|
||||
{
|
||||
updatePosition();
|
||||
}
|
||||
@@ -751,11 +752,12 @@ void LLVivoxVoiceClient::stateMachine()
|
||||
if((getState() != stateDisabled) && (getState() != stateDisableCleanup))
|
||||
{
|
||||
// User turned off voice support. Send the cleanup messages, close the socket, and reset.
|
||||
if(!mConnected)
|
||||
if(!mConnected || mTerminateDaemon)
|
||||
{
|
||||
// if voice was turned off after the daemon was launched but before we could connect to it, we may need to issue a kill.
|
||||
LL_INFOS("Voice") << "Disabling voice before connection to daemon, terminating." << LL_ENDL;
|
||||
killGateway();
|
||||
mTerminateDaemon = false;
|
||||
}
|
||||
|
||||
logout();
|
||||
@@ -796,7 +798,7 @@ void LLVivoxVoiceClient::stateMachine()
|
||||
// Voice is locked out, we must not launch the vivox daemon.
|
||||
setState(stateJail);
|
||||
}
|
||||
else if(!isGatewayRunning())
|
||||
else if(!isGatewayRunning() && gSavedSettings.getBOOL("EnableVoiceChat"))
|
||||
{
|
||||
if (true) // production build, not test
|
||||
{
|
||||
@@ -1281,6 +1283,7 @@ void LLVivoxVoiceClient::stateMachine()
|
||||
std::stringstream errs;
|
||||
errs << mVoiceAccountServerURI << "\n:UDP: 3478, 3479, 5060, 5062, 12000-17000";
|
||||
args["HOSTID"] = errs.str();
|
||||
mTerminateDaemon = true;
|
||||
LLNotificationsUtil::add("NoVoiceConnect", args);
|
||||
}
|
||||
else
|
||||
@@ -2759,6 +2762,7 @@ void LLVivoxVoiceClient::connectorCreateResponse(int statusCode, std::string &st
|
||||
std::stringstream errs;
|
||||
errs << mVoiceAccountServerURI << "\n:UDP: 3478, 3479, 5060, 5062, 12000-17000";
|
||||
args["HOSTID"] = errs.str();
|
||||
mTerminateDaemon = true;
|
||||
LLNotificationsUtil::add("NoVoiceConnect", args);
|
||||
}
|
||||
else
|
||||
@@ -2767,6 +2771,7 @@ void LLVivoxVoiceClient::connectorCreateResponse(int statusCode, std::string &st
|
||||
LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
|
||||
mVoiceVersion.serverVersion = versionID;
|
||||
mConnectorHandle = connectorHandle;
|
||||
mTerminateDaemon = false;
|
||||
if(getState() == stateConnectorStarting)
|
||||
{
|
||||
setState(stateConnectorStarted);
|
||||
@@ -6936,6 +6941,9 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
|
||||
*/
|
||||
// We don't need to process this, but we also shouldn't warn on it, since that confuses people.
|
||||
}
|
||||
else if (!stricmp(eventTypeCstr, "VoiceServiceConnectionStateChangedEvent"))
|
||||
{ // Yet another ignored event
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
////////////////////////////
|
||||
/// @name Channel stuff
|
||||
//@{
|
||||
// returns true if the user is currently in a proximal (local spatial) channel.
|
||||
// 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();
|
||||
|
||||
@@ -640,6 +640,8 @@ private:
|
||||
LLSocket::ptr_t mSocket;
|
||||
bool mConnected;
|
||||
|
||||
// We should kill the voice daemon in case of connection alert
|
||||
bool mTerminateDaemon;
|
||||
|
||||
LLPumpIO *mPump;
|
||||
friend class LLVivoxProtocolParser;
|
||||
|
||||
Reference in New Issue
Block a user