[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:
Inusaito Sayori
2014-06-07 06:27:36 -04:00
parent f63de0d0cc
commit fa0de18ffe
8 changed files with 179 additions and 32 deletions

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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),

View File

@@ -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;

View File

@@ -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;