Tiny update to voice code to avoid falling behind the Lindens

Adds support for secondlife:///app/voice SLapps
This commit is contained in:
Lirusaito
2013-07-16 05:41:14 -04:00
parent d497e0d10e
commit 4b210c1bbf
5 changed files with 144 additions and 118 deletions

View File

@@ -111,7 +111,6 @@ LLSD LLSpeakerUpdateModeratorEvent::getValue()
return ret;
}
LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
: LLEvent(source, "Speaker text moderation event")
{
@@ -254,15 +253,58 @@ bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_
return true;
}
//
// ModerationResponder
//
class ModerationResponder : public LLHTTPClient::ResponderIgnoreBody
{
public:
ModerationResponder(const LLUUID& session_id)
{
mSessionID = session_id;
}
/*virtual*/ void error(U32 status, const std::string& reason)
{
llwarns << "ModerationResponder error [status:" << status << "]: " << reason << llendl;
if ( gIMMgr )
{
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(mSessionID);
if (!floaterp) return;
//403 == you're not a mod
//should be disabled if you're not a moderator
if ( 403 == status )
{
floaterp->showSessionEventError(
"mute",
"not_a_mod_error");
}
else
{
floaterp->showSessionEventError(
"mute",
"generic_request_error");
}
}
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return moderationResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "ModerationResponder"; }
private:
LLUUID mSessionID;
};
//
// LLSpeakerMgr
//
LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
mVoiceChannel(channelp)
, mVoiceModerated(false)
, mModerateModeHandledFirstTime(false)
mVoiceChannel(channelp),
mVoiceModerated(false),
mModerateModeHandledFirstTime(false)
{
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
@@ -276,7 +318,10 @@ LLSpeakerMgr::~LLSpeakerMgr()
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
{
if (id.isNull()) return NULL;
if (id.isNull())
{
return NULL;
}
LLPointer<LLSpeaker> speakerp;
if (mSpeakers.find(id) == mSpeakers.end())
@@ -358,13 +403,11 @@ void LLSpeakerMgr::update(BOOL resort_ok)
// update status of all current speakers
BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++)
{
LLUUID speaker_id = speaker_it->first;
LLSpeaker* speakerp = speaker_it->second;
speaker_it++;
if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
{
speakerp->mSpeechVolume = LLVoiceClient::getInstance()->getCurrentPower(speaker_id);
@@ -461,22 +504,18 @@ void LLSpeakerMgr::update(BOOL resort_ok)
void LLSpeakerMgr::updateSpeakerList()
{
// are we bound to the currently active voice channel?
// Are we bound to the currently active voice channel?
if ((!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
{
std::set<LLUUID> participants;
LLVoiceClient::getInstance()->getParticipantList(participants);
// add new participants to our list of known speakers
for (std::set<LLUUID>::iterator participant_it = participants.begin();
participant_it != participants.end();
++participant_it)
// If we are, add all voice client participants to our list of known speakers
for (std::set<LLUUID>::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it)
{
setSpeaker(*participant_it,
LLVoiceClient::getInstance()->getDisplayName(*participant_it),
LLSpeaker::STATUS_VOICE_ACTIVE,
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
}
}
}
@@ -730,47 +769,10 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
}
}
}
class ModerationResponder : public LLHTTPClient::ResponderIgnoreBody
{
public:
ModerationResponder(const LLUUID& session_id)
{
mSessionID = session_id;
}
/*virtual*/ void error(U32 status, const std::string& reason)
{
llwarns << "ModerationResponder error [status:" << status << "]: " << reason << llendl;
if ( gIMMgr )
{
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(mSessionID);
if (!floaterp) return;
//403 == you're not a mod
//should be disabled if you're not a moderator
if ( 403 == status )
{
floaterp->showSessionEventError(
"mute",
"not_a_mod_error");
}
else
{
floaterp->showSessionEventError(
"mute",
"generic_request_error");
}
}
}
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return moderationResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "ModerationResponder"; }
private:
LLUUID mSessionID;
};
/*prep#
virtual void errorWithContent(U32 status, const std::string& reason, const LLSD& content)
llwarns << "ModerationResponder error [status:" << status << "]: " << content << llendl;
*/
void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
{
LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
@@ -957,4 +959,3 @@ void LLLocalSpeakerMgr::updateSpeakerList()
}
}
}

View File

@@ -964,4 +964,3 @@ void LLVoiceChannelP2P::setState(EState state)
LLRecentPeople::instance().add(mOtherUserID);
}
}*/

View File

@@ -30,6 +30,7 @@
#include "llviewerwindow.h"
#include "llvoicevivox.h"
#include "llviewernetwork.h"
#include "llcommandhandler.h"
#include "llhttpnode.h"
#include "llnotificationsutil.h"
#include "llsdserialize.h"
@@ -42,6 +43,38 @@ const F32 LLVoiceClient::VOLUME_DEFAULT = 0.5f;
const F32 LLVoiceClient::VOLUME_MAX = 1.0f;
// Support for secondlife:///app/voice SLapps
class LLVoiceHandler : public LLCommandHandler
{
public:
// requests will be throttled from a non-trusted browser
LLVoiceHandler() : LLCommandHandler("voice", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{
if (params[0].asString() == "effects")
{
LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
// If the voice client doesn't support voice effects, we can't handle effects SLapps
if (!effect_interface)
{
return false;
}
// Support secondlife:///app/voice/effects/refresh to update the voice effect list with new effects
if (params[1].asString() == "refresh")
{
effect_interface->refreshVoiceEffectLists(false);
return true;
}
}
return false;
}
};
LLVoiceHandler gVoiceHandler;
std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserver::EStatusType inStatus)
{
std::string result = "UNKNOWN";

View File

@@ -330,6 +330,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
mCaptureDeviceDirty(false),
mRenderDeviceDirty(false),
mSpatialCoordsDirty(false),
mIsInitialized(false),
mMuteMic(false),
mMuteMicDirty(false),
@@ -354,7 +355,9 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
mCaptureBufferRecording(false),
mCaptureBufferRecorded(false),
mCaptureBufferPlaying(false),
mPlayRequestCount(0)
mPlayRequestCount(0),
mAvatarNameCacheConnection()
{
mSpeakerVolume = scale_speaker_volume(0);
@@ -387,6 +390,10 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
LLVivoxVoiceClient::~LLVivoxVoiceClient()
{
if (mAvatarNameCacheConnection.connected())
{
mAvatarNameCacheConnection.disconnect();
}
}
//---------------------------------------------------
@@ -568,7 +575,7 @@ void LLVivoxVoiceClient::requestVoiceAccountProvision(S32 retries)
{
LLViewerRegion *region = gAgent.getRegion();
if ( region && mVoiceEnabled )
if ( region && (mVoiceEnabled || !mIsInitialized))
{
std::string url =
region->getCapability("ProvisionVoiceAccountRequest");
@@ -739,7 +746,7 @@ void LLVivoxVoiceClient::stateMachine()
setVoiceEnabled(false);
}
if(mVoiceEnabled)
if(mVoiceEnabled || !mIsInitialized)
{
updatePosition();
}
@@ -784,7 +791,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateDisabled
case stateDisabled:
if(mTuningMode || (mVoiceEnabled && !mAccountName.empty()))
if(mTuningMode || ((mVoiceEnabled || !mIsInitialized) && !mAccountName.empty()))
{
setState(stateStart);
}
@@ -1039,7 +1046,7 @@ void LLVivoxVoiceClient::stateMachine()
mTuningExitState = stateIdle;
setState(stateMicTuningStart);
}
else if(!mVoiceEnabled)
else if(!mVoiceEnabled && mIsInitialized)
{
// We never started up the connector. This will shut down the daemon.
setState(stateConnectorStopped);
@@ -1233,7 +1240,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateConnectorStart
case stateConnectorStart:
if(!mVoiceEnabled)
if(!mVoiceEnabled && mIsInitialized)
{
// We were never logged in. This will shut down the connector.
setState(stateLoggedOut);
@@ -1251,7 +1258,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateConnectorStarted
case stateConnectorStarted: // connector handle received
if(!mVoiceEnabled)
if(!mVoiceEnabled && mIsInitialized)
{
// We were never logged in. This will shut down the connector.
setState(stateLoggedOut);
@@ -1388,7 +1395,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateCreatingSessionGroup
case stateCreatingSessionGroup:
if(mSessionTerminateRequested || !mVoiceEnabled)
if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{
// *TODO: Question: is this the right way out of this state
setState(stateSessionTerminated);
@@ -1404,7 +1411,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateRetrievingParcelVoiceInfo
case stateRetrievingParcelVoiceInfo:
// wait until parcel voice info is received.
if(mSessionTerminateRequested || !mVoiceEnabled)
if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{
// if a terminate request has been received,
// bail and go to the stateSessionTerminated
@@ -1424,7 +1431,7 @@ void LLVivoxVoiceClient::stateMachine()
// Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
sendFriendsListUpdates();
if(mSessionTerminateRequested || !mVoiceEnabled)
if(mSessionTerminateRequested || (!mVoiceEnabled && mIsInitialized))
{
// TODO: Question: Is this the right way out of this state?
setState(stateSessionTerminated);
@@ -1505,7 +1512,7 @@ void LLVivoxVoiceClient::stateMachine()
}
// joinedAudioSession() will transition from here to stateSessionJoined.
if(!mVoiceEnabled)
if(!mVoiceEnabled && mIsInitialized)
{
// User bailed out during connect -- jump straight to teardown.
setState(stateSessionTerminated);
@@ -1552,7 +1559,7 @@ void LLVivoxVoiceClient::stateMachine()
notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
}
else if(!mVoiceEnabled)
else if(!mVoiceEnabled && mIsInitialized)
{
// User bailed out during connect -- jump straight to teardown.
setState(stateSessionTerminated);
@@ -1572,7 +1579,7 @@ void LLVivoxVoiceClient::stateMachine()
//MARK: stateRunning
case stateRunning: // steady state
// Disabling voice or disconnect requested.
if(!mVoiceEnabled || mSessionTerminateRequested)
if((!mVoiceEnabled && mIsInitialized) || mSessionTerminateRequested)
{
leaveAudioSession();
}
@@ -1619,6 +1626,8 @@ void LLVivoxVoiceClient::stateMachine()
mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
sendPositionalUpdate();
}
mIsInitialized = true;
}
break;
@@ -1652,7 +1661,7 @@ void LLVivoxVoiceClient::stateMachine()
// Always reset the terminate request flag when we get here.
mSessionTerminateRequested = false;
if(mVoiceEnabled && !mRelogRequested)
if((mVoiceEnabled || !mIsInitialized) && !mRelogRequested)
{
// Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state).
setState(stateNoChannel);
@@ -1680,7 +1689,7 @@ void LLVivoxVoiceClient::stateMachine()
mAccountHandle.clear();
cleanUp();
if(mVoiceEnabled && !mRelogRequested)
if((mVoiceEnabled || !mIsInitialized) && !mRelogRequested)
{
// User was logged out, but wants to be logged in. Send a new login request.
setState(stateNeedsLogin);
@@ -2804,29 +2813,15 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
LLAvatarName av_name;
if(LLAvatarNameCache::get(id, &av_name))
{
// *NOTE: For now, we feed legacy names to Vivox because I don't know
// if their service can support a mix of new and old clients with
// different sorts of names.
// *NOTE: We feed legacy names to Vivox because we don't know if their service
// can support a mix of new and old clients with different sorts of names.
std::string name = av_name.getLegacyName();
const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
bool canSeeMeOnline = false;
if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
canSeeMeOnline = true;
// When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary.
if(buddy)
{
// This buddy is already in both lists.
if(name != buddy->mDisplayName)
{
// The buddy is in the list with the wrong name. Update it with the correct name.
LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
// This buddy is already in both lists (vivox buddies and avatar cache).
// Trust the avatar cache more for the display name (vivox display name are notoriously wrong)
buddy->mDisplayName = name;
buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
}
}
else
{
@@ -2835,20 +2830,19 @@ void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
buddy->mUUID = id;
}
// In all the above cases, the buddy is in the SL friends list (which is how we got here).
buddy->mInSLFriends = true;
buddy->mCanSeeMeOnline = canSeeMeOnline;
const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
buddy->mCanSeeMeOnline = (relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
// In all the above cases, the buddy is in the SL friends list and tha name has been resolved (which is how we got here).
buddy->mNameResolved = true;
buddy->mInSLFriends = true;
}
else
{
// This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has.
// This name hasn't been looked up yet in the avatar cache. Don't do anything with this buddy list entry until it has.
if(buddy)
{
buddy->mNameResolved = false;
}
// Initiate a lookup.
// The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
lookupName(id);
@@ -2956,13 +2950,12 @@ void LLVivoxVoiceClient::sendFriendsListUpdates()
{
std::ostringstream stream;
if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
if(buddy->mInSLFriends && !buddy->mInVivoxBuddies)
{
if(mNumberOfAliases > 0)
{
// Add (or update) this entry in the vivox buddy list
buddy->mInVivoxBuddies = true;
buddy->mNeedsNameUpdate = false;
LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
stream
<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.BuddySet.1\">"
@@ -3847,8 +3840,7 @@ void LLVivoxVoiceClient::participantUpdatedEvent(
voice participant mIsModeratorMuted is changed after speakers are updated in Speaker Manager
and event is not fired.
So, we have to call LLSpeakerMgr::update() here. In any case it is better than call it
in LLCallFloater::draw()
So, we have to call LLSpeakerMgr::update() here.
*/
LLVoiceChannel* voice_cnl = LLVoiceChannel::getCurrentVoiceChannel();
@@ -4078,7 +4070,7 @@ void LLVivoxVoiceClient::messageEvent(
sessionState *session = findSession(sessionHandle);
if(session)
{
bool is_busy = gAgent.getBusy();
bool is_do_not_disturb = gAgent.getBusy();
bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
bool is_linden = LLMuteList::getInstance()->isLinden(session->mName);
LLChat chat;
@@ -4091,9 +4083,9 @@ void LLVivoxVoiceClient::messageEvent(
chat.mFromName = session->mName;
chat.mSourceType = CHAT_SOURCE_AGENT;
if(is_busy && !is_linden)
if(is_do_not_disturb && !is_linden)
{
// TODO: Question: Return busy mode response here? Or maybe when session is started instead?
// TODO: Question: Return do not disturb mode response here? Or maybe when session is started instead?
}
LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
@@ -5985,7 +5977,6 @@ LLVivoxVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
mNameResolved = false;
mInVivoxBuddies = false;
mInSLFriends = false;
mNeedsNameUpdate = false;
}
void LLVivoxVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
@@ -6024,11 +6015,7 @@ LLVivoxVoiceClient::buddyListEntry *LLVivoxVoiceClient::addBuddy(const std::stri
result = new buddyListEntry(uri);
result->mDisplayName = displayName;
if(IDFromName(uri, result->mUUID))
{
// Extracted UUID from name successfully.
}
else
if (!IDFromName(uri, result->mUUID))
{
LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
}
@@ -6328,18 +6315,19 @@ void LLVivoxVoiceClient::notifyFriendObservers()
void LLVivoxVoiceClient::lookupName(const LLUUID &id)
{
LLAvatarNameCache::get(id,
boost::bind(&LLVivoxVoiceClient::onAvatarNameCache,
this, _1, _2));
if (mAvatarNameCacheConnection.connected())
{
mAvatarNameCacheConnection.disconnect();
}
mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLVivoxVoiceClient::onAvatarNameCache, this, _1, _2));
}
void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
// For Vivox, we use the legacy name because I'm uncertain whether or
// not their service can tolerate switching to Username or Display Name
std::string legacy_name = av_name.getLegacyName();
avatarNameResolved(agent_id, legacy_name);
mAvatarNameCacheConnection.disconnect();
std::string display_name = av_name.mDisplayName;
avatarNameResolved(agent_id, display_name);
}
void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
@@ -7401,6 +7389,8 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
}
else if (!stricmp("Buddy", tag))
{
// NOTE : Vivox does *not* give reliable display name for Buddy tags
// We don't take those very seriously as a result...
LLVivoxVoiceClient::getInstance()->processBuddyListEntry(uriString, displayNameString);
}
else if (!stricmp("BlockRule", tag))

View File

@@ -564,7 +564,6 @@ protected:
bool mNameResolved;
bool mInSLFriends;
bool mInVivoxBuddies;
bool mNeedsNameUpdate;
};
typedef std::map<std::string, buddyListEntry*> buddyListMap;
@@ -623,6 +622,7 @@ protected:
void lookupName(const LLUUID &id);
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
void avatarNameResolved(const LLUUID &id, const std::string &name);
boost::signals2::connection mAvatarNameCacheConnection;
/////////////////////////////
// Voice fonts
@@ -724,6 +724,8 @@ private:
bool mCaptureDeviceDirty;
bool mRenderDeviceDirty;
bool mIsInitialized;
bool checkParcelChanged(bool update = false);
// This should be called when the code detects we have changed parcels.
@@ -1014,3 +1016,4 @@ protected:
#endif //LL_VIVOX_VOICE_CLIENT_H