Add bulk speaker updates. Sped up speaker fetching by disabling list sorting during bulk updates.
This commit is contained in:
@@ -125,6 +125,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
|
|||||||
mNeedsScroll(false),
|
mNeedsScroll(false),
|
||||||
mCanSelect(true),
|
mCanSelect(true),
|
||||||
mColumnsDirty(false),
|
mColumnsDirty(false),
|
||||||
|
mSortEnabled(true),
|
||||||
mMaxItemCount(INT_MAX),
|
mMaxItemCount(INT_MAX),
|
||||||
mMaxContentWidth(0),
|
mMaxContentWidth(0),
|
||||||
mBorderThickness( 2 ),
|
mBorderThickness( 2 ),
|
||||||
@@ -2301,6 +2302,16 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLScrollListCtrl::setSortEnabled(bool sort)
|
||||||
|
{
|
||||||
|
bool update = sort && !mSortEnabled;
|
||||||
|
mSortEnabled = sort;
|
||||||
|
if (update)
|
||||||
|
{
|
||||||
|
updateSort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
S32 LLScrollListCtrl::getLinesPerPage()
|
S32 LLScrollListCtrl::getLinesPerPage()
|
||||||
{
|
{
|
||||||
//if mPageLines is NOT provided display all item
|
//if mPageLines is NOT provided display all item
|
||||||
@@ -2942,7 +2953,7 @@ std::string LLScrollListCtrl::getSortColumnName()
|
|||||||
|
|
||||||
BOOL LLScrollListCtrl::hasSortOrder() const
|
BOOL LLScrollListCtrl::hasSortOrder() const
|
||||||
{
|
{
|
||||||
return !mSortColumns.empty();
|
return mSortEnabled && !mSortColumns.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLScrollListCtrl::clearSortOrder()
|
void LLScrollListCtrl::clearSortOrder()
|
||||||
|
|||||||
@@ -322,6 +322,7 @@ public:
|
|||||||
BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
|
BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
|
||||||
BOOL hasSortOrder() const;
|
BOOL hasSortOrder() const;
|
||||||
void clearSortOrder();
|
void clearSortOrder();
|
||||||
|
void setSortEnabled(bool sort);
|
||||||
|
|
||||||
template<typename T> S32 selectMultiple(const std::vector<T>& vec)
|
template<typename T> S32 selectMultiple(const std::vector<T>& vec)
|
||||||
{
|
{
|
||||||
@@ -423,6 +424,7 @@ private:
|
|||||||
bool mDisplayColumnHeaders;
|
bool mDisplayColumnHeaders;
|
||||||
bool mColumnsDirty;
|
bool mColumnsDirty;
|
||||||
bool mColumnWidthsDirty;
|
bool mColumnWidthsDirty;
|
||||||
|
bool mSortEnabled;
|
||||||
|
|
||||||
mutable item_list mItemList;
|
mutable item_list mItemList;
|
||||||
|
|
||||||
|
|||||||
@@ -58,10 +58,13 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
|
|||||||
mSpeakerClearListener = new SpeakerClearListener(*this);
|
mSpeakerClearListener = new SpeakerClearListener(*this);
|
||||||
//mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this);
|
//mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this);
|
||||||
mSpeakerMuteListener = new SpeakerMuteListener(*this);
|
mSpeakerMuteListener = new SpeakerMuteListener(*this);
|
||||||
|
mSpeakerBatchBeginListener = new SpeakerBatchBeginListener(*this);
|
||||||
|
mSpeakerBatchEndListener = new SpeakerBatchEndListener(*this);
|
||||||
mSpeakerMgr->addListener(mSpeakerAddListener, "add");
|
mSpeakerMgr->addListener(mSpeakerAddListener, "add");
|
||||||
mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
|
mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
|
||||||
mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
|
mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
|
||||||
|
mSpeakerMgr->addListener(mSpeakerBatchBeginListener, "batch_begin");
|
||||||
|
mSpeakerMgr->addListener(mSpeakerBatchEndListener, "batch_end");
|
||||||
//mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
|
//mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +381,16 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLParticipantList::onSpeakerBatchBeginEvent()
|
||||||
|
{
|
||||||
|
mAvatarList->setSortEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLParticipantList::onSpeakerBatchEndEvent()
|
||||||
|
{
|
||||||
|
mAvatarList->setSortEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
|
void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
|
||||||
{
|
{
|
||||||
//if (mExcludeAgent && gAgent.getID() == avatar_id) return;
|
//if (mExcludeAgent && gAgent.getID() == avatar_id) return;
|
||||||
@@ -468,6 +481,17 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::
|
|||||||
return mParent.onSpeakerMuteEvent(event, userdata);
|
return mParent.onSpeakerMuteEvent(event, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLParticipantList::SpeakerBatchBeginListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
|
||||||
|
{
|
||||||
|
mParent.onSpeakerBatchBeginEvent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool LLParticipantList::SpeakerBatchEndListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
|
||||||
|
{
|
||||||
|
mParent.onSpeakerBatchEndEvent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Singu Note: The following functions are actually of the LLParticipantListMenu class, but we haven't married lists with menus yet.
|
// Singu Note: The following functions are actually of the LLParticipantListMenu class, but we haven't married lists with menus yet.
|
||||||
void LLParticipantList::toggleAllowTextChat(const LLSD& userdata)
|
void LLParticipantList::toggleAllowTextChat(const LLSD& userdata)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ protected:
|
|||||||
bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
//bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
//bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
|
void onSpeakerBatchBeginEvent();
|
||||||
|
void onSpeakerBatchEndEvent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of listeners implementing LLOldEvents::LLSimpleListener.
|
* List of listeners implementing LLOldEvents::LLSimpleListener.
|
||||||
@@ -126,6 +128,20 @@ protected:
|
|||||||
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SpeakerBatchBeginListener : public BaseSpeakerListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpeakerBatchBeginListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
|
||||||
|
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpeakerBatchEndListener : public BaseSpeakerListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpeakerBatchEndListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
|
||||||
|
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menu used in the participant list.
|
* Menu used in the participant list.
|
||||||
class LLParticipantListMenu : public LLListContextMenu
|
class LLParticipantListMenu : public LLListContextMenu
|
||||||
@@ -202,6 +218,8 @@ private:
|
|||||||
LLPointer<SpeakerClearListener> mSpeakerClearListener;
|
LLPointer<SpeakerClearListener> mSpeakerClearListener;
|
||||||
//LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
|
//LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
|
||||||
LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
|
LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
|
||||||
|
LLPointer<SpeakerBatchBeginListener> mSpeakerBatchBeginListener;
|
||||||
|
LLPointer<SpeakerBatchEndListener> mSpeakerBatchEndListener;
|
||||||
|
|
||||||
validate_speaker_callback_t mValidateSpeakerCallback;
|
validate_speaker_callback_t mValidateSpeakerCallback;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -338,7 +338,20 @@ LLSpeakerMgr::~LLSpeakerMgr()
|
|||||||
delete mSpeakerDelayRemover;
|
delete mSpeakerDelayRemover;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
|
void LLSpeakerMgr::setSpeakers(const std::vector<LLSpeakerMgr::speaker_entry_t>& speakers)
|
||||||
|
{
|
||||||
|
if (!speakers.empty())
|
||||||
|
{
|
||||||
|
fireEvent(new LLOldEvents::LLEvent(this), "batch_begin");
|
||||||
|
for (auto entry : speakers)
|
||||||
|
{
|
||||||
|
setSpeaker(entry.id, entry.name, entry.status, entry.type, entry.moderator, entry.moderator_muted_text);
|
||||||
|
}
|
||||||
|
fireEvent(new LLOldEvents::LLEvent(this), "batch_end");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type, bool moderator, bool moderator_muted_text)
|
||||||
{
|
{
|
||||||
LLUUID session_id = getSessionID();
|
LLUUID session_id = getSessionID();
|
||||||
if (id.isNull() || (id == session_id))
|
if (id.isNull() || (id == session_id))
|
||||||
@@ -347,34 +360,37 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLPointer<LLSpeaker> speakerp;
|
LLPointer<LLSpeaker> speakerp;
|
||||||
if (mSpeakers.find(id) == mSpeakers.end())
|
auto it = mSpeakers.find(id);
|
||||||
|
if (it == mSpeakers.end() || it->second.isNull())
|
||||||
{
|
{
|
||||||
speakerp = new LLSpeaker(id, name, type);
|
speakerp = new LLSpeaker(id, name, type);
|
||||||
speakerp->mStatus = status;
|
speakerp->mStatus = status;
|
||||||
|
speakerp->mIsModerator = moderator;
|
||||||
|
speakerp->mModeratorMutedText = moderator_muted_text;
|
||||||
mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
|
mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
|
||||||
mSpeakersSorted.push_back(speakerp);
|
mSpeakersSorted.push_back(speakerp);
|
||||||
LL_DEBUGS("Speakers") << "Added speaker " << id << LL_ENDL;
|
|
||||||
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
|
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
speakerp = findSpeaker(id);
|
speakerp = it->second;
|
||||||
if (speakerp.notNull())
|
bool update_moderator = (bool)speakerp->mIsModerator != moderator;
|
||||||
|
|
||||||
|
// keep highest priority status (lowest value) instead of overriding current value
|
||||||
|
speakerp->mStatus = llmin(speakerp->mStatus, status);
|
||||||
|
speakerp->mIsModerator = moderator;
|
||||||
|
speakerp->mModeratorMutedText = moderator_muted_text;
|
||||||
|
// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
|
||||||
|
// we need to override speakers that we think are objects when we find out they are really
|
||||||
|
// residents
|
||||||
|
if (type == LLSpeaker::SPEAKER_AGENT)
|
||||||
{
|
{
|
||||||
// keep highest priority status (lowest value) instead of overriding current value
|
speakerp->mType = LLSpeaker::SPEAKER_AGENT;
|
||||||
speakerp->mStatus = llmin(speakerp->mStatus, status);
|
speakerp->lookupName();
|
||||||
// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
|
|
||||||
// we need to override speakers that we think are objects when we find out they are really
|
|
||||||
// residents
|
|
||||||
if (type == LLSpeaker::SPEAKER_AGENT)
|
|
||||||
{
|
|
||||||
speakerp->mType = LLSpeaker::SPEAKER_AGENT;
|
|
||||||
speakerp->lookupName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
if (update_moderator)
|
||||||
{
|
{
|
||||||
LL_WARNS("Speakers") << "Speaker " << id << " not found" << LL_ENDL;
|
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,13 +550,17 @@ void LLSpeakerMgr::updateSpeakerList()
|
|||||||
std::set<LLUUID> participants;
|
std::set<LLUUID> participants;
|
||||||
LLVoiceClient::getInstance()->getParticipantList(participants);
|
LLVoiceClient::getInstance()->getParticipantList(participants);
|
||||||
// If we are, add all voice client participants to our list of known speakers
|
// If we are, add all voice client participants to our list of known speakers
|
||||||
|
std::vector<speaker_entry_t> speakers;
|
||||||
|
speakers.reserve(participants.size());
|
||||||
for (std::set<LLUUID>::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it)
|
for (std::set<LLUUID>::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it)
|
||||||
{
|
{
|
||||||
setSpeaker(*participant_it,
|
speakers.emplace_back(speaker_entry_t(
|
||||||
LLVoiceClient::getInstance()->getDisplayName(*participant_it),
|
*participant_it,
|
||||||
LLSpeaker::STATUS_VOICE_ACTIVE,
|
LLSpeaker::STATUS_VOICE_ACTIVE,
|
||||||
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
|
LLVoiceClient::getInstance()->getDisplayName(*participant_it),
|
||||||
|
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)));
|
||||||
}
|
}
|
||||||
|
setSpeakers(speakers);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -569,10 +589,11 @@ void LLSpeakerMgr::updateSpeakerList()
|
|||||||
}
|
}
|
||||||
else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
|
else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
|
||||||
{
|
{
|
||||||
|
std::vector<speaker_entry_t> speakers;
|
||||||
|
speakers.reserve(gdatap->mMembers.size());
|
||||||
|
|
||||||
// Add group members when we get the complete list (note: can take a while before we get that list)
|
// 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();
|
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())
|
while (member_it != gdatap->mMembers.end())
|
||||||
{
|
{
|
||||||
LLGroupMemberData* member = member_it->second;
|
LLGroupMemberData* member = member_it->second;
|
||||||
@@ -581,16 +602,16 @@ void LLSpeakerMgr::updateSpeakerList()
|
|||||||
const std::string& localized_online();
|
const std::string& localized_online();
|
||||||
if ((member->getOnlineStatus() == localized_online()) && (mSpeakers.find(id) == mSpeakers.end()))
|
if ((member->getOnlineStatus() == localized_online()) && (mSpeakers.find(id) == mSpeakers.end()))
|
||||||
{
|
{
|
||||||
LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT);
|
speakers.emplace_back(speaker_entry_t(
|
||||||
speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR);
|
id,
|
||||||
updated++;
|
LLSpeaker::STATUS_VOICE_ACTIVE,
|
||||||
|
"",
|
||||||
|
LLSpeaker::SPEAKER_AGENT,
|
||||||
|
(member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR));
|
||||||
}
|
}
|
||||||
++member_it;
|
++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;
|
|
||||||
}
|
}
|
||||||
|
setSpeakers(speakers);
|
||||||
mSpeakerListUpdated = true;
|
mSpeakerListUpdated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -617,7 +638,7 @@ void LLSpeakerMgr::updateSpeakerList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Always add the current agent (it has to be there...). Will do nothing if already there.
|
// 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);
|
setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
|
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
|
||||||
@@ -737,6 +758,7 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
|
|||||||
{
|
{
|
||||||
if ( !speakers.isMap() ) return;
|
if ( !speakers.isMap() ) return;
|
||||||
|
|
||||||
|
std::vector<speaker_entry_t> speakerentries;
|
||||||
if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
|
if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
|
||||||
{
|
{
|
||||||
LLSD::map_const_iterator speaker_it;
|
LLSD::map_const_iterator speaker_it;
|
||||||
@@ -744,26 +766,21 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
|
|||||||
speaker_it != speakers["agent_info"].endMap();
|
speaker_it != speakers["agent_info"].endMap();
|
||||||
++speaker_it)
|
++speaker_it)
|
||||||
{
|
{
|
||||||
LLUUID agent_id(speaker_it->first);
|
bool moderator = false;
|
||||||
|
bool moderator_muted = false;
|
||||||
LLPointer<LLSpeaker> speakerp = setSpeaker(
|
if (speaker_it->second.isMap())
|
||||||
agent_id,
|
|
||||||
LLStringUtil::null,
|
|
||||||
LLSpeaker::STATUS_TEXT_ONLY);
|
|
||||||
|
|
||||||
if ( speaker_it->second.isMap() )
|
|
||||||
{
|
{
|
||||||
BOOL is_moderator = speakerp->mIsModerator;
|
moderator = speaker_it->second["is_moderator"];
|
||||||
speakerp->mIsModerator = speaker_it->second["is_moderator"];
|
moderator_muted = speaker_it->second["mutes"]["text"];
|
||||||
speakerp->mModeratorMutedText =
|
|
||||||
speaker_it->second["mutes"]["text"];
|
|
||||||
// Fire event only if moderator changed
|
|
||||||
if ( is_moderator != speakerp->mIsModerator )
|
|
||||||
{
|
|
||||||
LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << LL_ENDL;
|
|
||||||
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
speakerentries.emplace_back(
|
||||||
|
LLUUID(speaker_it->first),
|
||||||
|
LLSpeaker::STATUS_TEXT_ONLY,
|
||||||
|
"",
|
||||||
|
LLSpeaker::SPEAKER_AGENT,
|
||||||
|
moderator,
|
||||||
|
moderator_muted
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
|
else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
|
||||||
@@ -775,22 +792,20 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
|
|||||||
speaker_it != speakers["agents"].endArray();
|
speaker_it != speakers["agents"].endArray();
|
||||||
++speaker_it)
|
++speaker_it)
|
||||||
{
|
{
|
||||||
const LLUUID agent_id = (*speaker_it).asUUID();
|
speakerentries.emplace_back((*speaker_it).asUUID());
|
||||||
|
|
||||||
LLPointer<LLSpeaker> speakerp = setSpeaker(
|
|
||||||
agent_id,
|
|
||||||
LLStringUtil::null,
|
|
||||||
LLSpeaker::STATUS_TEXT_ONLY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LLSpeakerMgr::setSpeakers(speakerentries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
||||||
{
|
{
|
||||||
if ( !update.isMap() ) return;
|
if ( !update.isMap() ) return;
|
||||||
|
|
||||||
|
std::vector<speaker_entry_t> speakerentries;
|
||||||
if ( update.has("agent_updates") && update["agent_updates"].isMap() )
|
if ( update.has("agent_updates") && update["agent_updates"].isMap() )
|
||||||
{
|
{
|
||||||
|
|
||||||
LLSD::map_const_iterator update_it;
|
LLSD::map_const_iterator update_it;
|
||||||
for(
|
for(
|
||||||
update_it = update["agent_updates"].beginMap();
|
update_it = update["agent_updates"].beginMap();
|
||||||
@@ -800,8 +815,11 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
LLUUID agent_id(update_it->first);
|
LLUUID agent_id(update_it->first);
|
||||||
LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
|
LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
|
||||||
|
|
||||||
LLSD agent_data = update_it->second;
|
bool new_speaker = false;
|
||||||
|
bool moderator = false;
|
||||||
|
bool moderator_muted = false;
|
||||||
|
|
||||||
|
LLSD agent_data = update_it->second;
|
||||||
if (agent_data.isMap() && agent_data.has("transition"))
|
if (agent_data.isMap() && agent_data.has("transition"))
|
||||||
{
|
{
|
||||||
if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
|
if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
|
||||||
@@ -811,15 +829,17 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
else if (agent_data["transition"].asString() == "ENTER")
|
else if (agent_data["transition"].asString() == "ENTER")
|
||||||
{
|
{
|
||||||
// add or update speaker
|
// add or update speaker
|
||||||
speakerp = setSpeaker(agent_id);
|
new_speaker = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LL_WARNS() << "bad membership list update from 'agent_updates' for agent " << agent_id << ", transition " << ll_print_sd(agent_data["transition"]) << LL_ENDL;
|
LL_WARNS() << "bad membership list update from 'agent_updates' for agent " << agent_id << ", transition " << ll_print_sd(agent_data["transition"]) << LL_ENDL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (speakerp.isNull() && !new_speaker)
|
||||||
if (speakerp.isNull()) continue;
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// should have a valid speaker from this point on
|
// should have a valid speaker from this point on
|
||||||
if (agent_data.isMap() && agent_data.has("info"))
|
if (agent_data.isMap() && agent_data.has("info"))
|
||||||
@@ -828,21 +848,21 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
|
|
||||||
if (agent_info.has("is_moderator"))
|
if (agent_info.has("is_moderator"))
|
||||||
{
|
{
|
||||||
BOOL is_moderator = speakerp->mIsModerator;
|
moderator = agent_info["is_moderator"];
|
||||||
speakerp->mIsModerator = agent_info["is_moderator"];
|
|
||||||
// Fire event only if moderator changed
|
|
||||||
if ( is_moderator != speakerp->mIsModerator )
|
|
||||||
{
|
|
||||||
LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << LL_ENDL;
|
|
||||||
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (agent_info.has("mutes"))
|
if (agent_info.has("mutes"))
|
||||||
{
|
{
|
||||||
speakerp->mModeratorMutedText = agent_info["mutes"]["text"];
|
moderator_muted = agent_info["mutes"]["text"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
speakerentries.emplace_back(
|
||||||
|
agent_id,
|
||||||
|
LLSpeaker::STATUS_TEXT_ONLY,
|
||||||
|
"",
|
||||||
|
LLSpeaker::SPEAKER_AGENT,
|
||||||
|
moderator,
|
||||||
|
moderator_muted
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( update.has("updates") && update["updates"].isMap() )
|
else if ( update.has("updates") && update["updates"].isMap() )
|
||||||
@@ -864,7 +884,9 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
else if ( agent_transition == "ENTER")
|
else if ( agent_transition == "ENTER")
|
||||||
{
|
{
|
||||||
// add or update speaker
|
// add or update speaker
|
||||||
speakerp = setSpeaker(agent_id);
|
speakerentries.emplace_back(
|
||||||
|
agent_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -872,6 +894,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LLSpeakerMgr::setSpeakers(speakerentries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
|
void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
|
||||||
@@ -1039,10 +1062,13 @@ void LLLocalSpeakerMgr::updateSpeakerList()
|
|||||||
// pick up non-voice speakers in chat range
|
// pick up non-voice speakers in chat range
|
||||||
uuid_vec_t avatar_ids;
|
uuid_vec_t avatar_ids;
|
||||||
LLWorld::getInstance()->getAvatars(&avatar_ids, nullptr, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
|
LLWorld::getInstance()->getAvatars(&avatar_ids, nullptr, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
|
||||||
|
std::vector<speaker_entry_t> speakers;
|
||||||
|
speakers.reserve(avatar_ids.size());
|
||||||
for (const auto& id : avatar_ids)
|
for (const auto& id : avatar_ids)
|
||||||
{
|
{
|
||||||
setSpeaker(id);
|
speakers.emplace_back(id);
|
||||||
}
|
}
|
||||||
|
setSpeakers(speakers);
|
||||||
|
|
||||||
// check if text only speakers have moved out of chat range
|
// check if text only speakers have moved out of chat range
|
||||||
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
|
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
|
||||||
|
|||||||
@@ -230,10 +230,32 @@ public:
|
|||||||
void update(BOOL resort_ok);
|
void update(BOOL resort_ok);
|
||||||
void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
|
void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
|
||||||
void speakerChatted(const LLUUID& speaker_id);
|
void speakerChatted(const LLUUID& speaker_id);
|
||||||
|
|
||||||
|
struct speaker_entry_t
|
||||||
|
{
|
||||||
|
speaker_entry_t(const LLUUID& id,
|
||||||
|
LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
|
||||||
|
const std::string& name = LLStringUtil::null,
|
||||||
|
LLSpeaker::ESpeakerType type = LLSpeaker::SPEAKER_AGENT,
|
||||||
|
const bool moderator = false,
|
||||||
|
const bool moderator_muted_text = false) :
|
||||||
|
id(id), name(name), status(status), type(type), moderator(moderator), moderator_muted_text(moderator_muted_text)
|
||||||
|
{}
|
||||||
|
const LLUUID id;
|
||||||
|
const std::string name;
|
||||||
|
const LLSpeaker::ESpeakerStatus status;
|
||||||
|
const LLSpeaker::ESpeakerType type;
|
||||||
|
const bool moderator;
|
||||||
|
const bool moderator_muted_text;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setSpeakers(const std::vector<speaker_entry_t>& speakers);
|
||||||
LLPointer<LLSpeaker> setSpeaker(const LLUUID& id,
|
LLPointer<LLSpeaker> setSpeaker(const LLUUID& id,
|
||||||
const std::string& name = LLStringUtil::null,
|
const std::string& name = LLStringUtil::null,
|
||||||
LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
|
LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
|
||||||
LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT);
|
LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT,
|
||||||
|
bool moderator = false,
|
||||||
|
bool moderator_muted_text = false);
|
||||||
|
|
||||||
BOOL isVoiceActive();
|
BOOL isVoiceActive();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user