summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llavatarlistitem.cpp22
-rw-r--r--indra/newview/llavatarlistitem.h1
-rw-r--r--indra/newview/llcallfloater.cpp235
-rw-r--r--indra/newview/llcallfloater.h35
-rw-r--r--indra/newview/llparticipantlist.cpp21
-rw-r--r--indra/newview/llparticipantlist.h6
6 files changed, 289 insertions, 31 deletions
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index bbe5cdcc4a..76dce622ed 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -184,6 +184,28 @@ void LLAvatarListItem::setHighlight(const std::string& highlight)
setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
}
+void LLAvatarListItem::setStyle(const LLStyle::Params& new_style)
+{
+// LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle = new_style);
+
+ // Active group should be bold.
+ LLFontDescriptor new_desc(mAvatarName->getDefaultFont()->getFontDesc());
+
+ new_desc.setStyle(new_style.font()->getFontDesc().getStyle());
+ // *NOTE dzaporozhan
+ // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font
+ // is predefined as bold (SansSerifSmallBold, for example)
+// new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+
+//
+ mAvatarNameStyle.font = new_font;
+
+ // *NOTE: You cannot set the style on a text box anymore, you must
+ // rebuild the text. This will cause problems if the text contains
+ // hyperlinks, as their styles will be wrong.
+ mAvatarName->setText(mAvatarName->getText(), mAvatarNameStyle/* = new_style*/);
+}
void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
{
if (mAvatarId.notNull())
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index df8b04126e..ad85d5fa87 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -73,6 +73,7 @@ public:
void setOnline(bool online);
void setName(const std::string& name);
void setHighlight(const std::string& highlight);
+ void setStyle(const LLStyle::Params& new_style);
void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
void setLastInteractionTime(U32 secs_since);
//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 2521bde8fa..fe4f0c5525 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -89,6 +89,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mAgentPanel(NULL)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
+, mInitParticipantsVoiceState(false)
{
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
@@ -100,6 +101,8 @@ LLCallFloater::~LLCallFloater()
delete mPaticipants;
mPaticipants = NULL;
+ mAvatarListRefreshConnection.disconnect();
+
// Don't use LLVoiceClient::getInstance() here
// singleton MAY have already been destroyed.
if(gVoiceClient)
@@ -114,6 +117,8 @@ BOOL LLCallFloater::postBuild()
{
LLDockableFloater::postBuild();
mAvatarList = getChild<LLAvatarList>("speakers_list");
+ mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this));
+
childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
@@ -165,8 +170,7 @@ void LLCallFloater::onChange()
{
if (NULL == mPaticipants) return;
- mPaticipants->refreshVoiceState();
-
+ updateParticipantsVoiceState();
}
@@ -291,7 +295,23 @@ void LLCallFloater::refreshPartisipantList()
{
mAvatarList->setNoItemsCommentText(getString("no_one_near"));
}
- mPaticipants->refreshVoiceState();
+
+ // we have to made delayed initialization of voice state of participant list.
+ // it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed().
+ mInitParticipantsVoiceState = true;
+ }
+}
+
+void LLCallFloater::onAvatarListRefreshed()
+{
+ if (mInitParticipantsVoiceState)
+ {
+ initParticipantsVoiceState();
+ mInitParticipantsVoiceState = false;
+ }
+ else
+ {
+ updateParticipantsVoiceState();
}
}
@@ -393,4 +413,213 @@ void LLCallFloater::updateAgentModeratorState()
}
mAgentPanel->childSetValue("user_text", name);
}
+
+void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
+{
+ // Get a list of participants from VoiceClient
+ LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList();
+ if (voice_map)
+ {
+ for (LLVoiceClient::participantMap::const_iterator iter = voice_map->begin();
+ iter != voice_map->end(); ++iter)
+ {
+ LLUUID id = (*iter).second->mAvatarID;
+ speakers_uuids.push_back(id);
+ }
+ }
+}
+
+void LLCallFloater::initParticipantsVoiceState()
+{
+ // Set initial status for each participant in the list.
+ std::vector<LLPanel*> items;
+ mAvatarList->getItems(items);
+ std::vector<LLPanel*>::const_iterator
+ it = items.begin(),
+ it_end = items.end();
+
+
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+
+ for(; it != it_end; ++it)
+ {
+ LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
+
+ if (!item) continue;
+
+ LLUUID speaker_id = item->getAvatarId();
+
+ std::vector<LLUUID>::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id);
+
+ // If an avatarID assigned to a panel is found in a speakers list
+ // obtained from VoiceClient we assign the JOINED status to the owner
+ // of this avatarID.
+ if (speaker_iter != speakers_uuids.end())
+ {
+ setState(item, STATE_JOINED);
+ }
+ else
+ {
+ LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id);
+ // If someone has already left the call before, we create his
+ // avatar row panel with HAS_LEFT status and remove it after
+ // the timeout, otherwise we create a panel with INVITED status
+ if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall)
+ {
+ setState(item, STATE_LEFT);
+ }
+ else
+ {
+ setState(item, STATE_INVITED);
+ }
+ }
+ }
+}
+
+void LLCallFloater::updateParticipantsVoiceState()
+{
+ std::vector<LLUUID> speakers_list;
+
+ // Get a list of participants from VoiceClient
+ LLVoiceClient::participantMap *map = gVoiceClient->getParticipantList();
+ if (!map) return;
+
+ for (LLVoiceClient::participantMap::const_iterator iter = map->begin();
+ iter != map->end(); ++iter)
+ {
+ LLUUID id = (*iter).second->mAvatarID;
+// if ( id != gAgent.getID() )
+ {
+ speakers_list.push_back(id);
+/*
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(id));
+ if (item)
+ {
+ setState(item, STATE_JOINED);
+ }
+*/
+
+ }
+ }
+
+ // Updating the status for each participant.
+ std::vector<LLPanel*> items;
+ mAvatarList->getItems(items);
+ std::vector<LLPanel*>::const_iterator
+ it = items.begin(),
+ it_end = items.end();
+
+ for(; it != it_end; ++it)
+ {
+ LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
+ if (!item) continue;
+
+ const LLUUID participant_id = item->getAvatarId();
+ bool found = false;
+
+ std::vector<LLUUID>::iterator speakers_iter = std::find(speakers_list.begin(), speakers_list.end(), participant_id);
+
+ lldebugs << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << llendl;
+
+ // If an avatarID assigned to a panel is found in a speakers list
+ // obtained from VoiceClient we assign the JOINED status to the owner
+ // of this avatarID.
+ if (speakers_iter != speakers_list.end())
+ {
+ setState(item, STATE_JOINED);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id);
+ if (speaker.isNull())
+ continue;
+ speaker->mHasLeftCurrentCall = FALSE;
+
+ speakers_list.erase(speakers_iter);
+ found = true;
+ }
+
+ // If an avatarID is not found in a speakers list from VoiceClient and
+ // a panel with this ID has a JOINED status this means that this person
+ // HAS LEFT the call.
+ if (!found)
+ {
+ if ((getState(participant_id) == STATE_JOINED))
+ {
+ setState(item, STATE_LEFT);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
+ if (speaker.isNull())
+ continue;
+
+ speaker->mHasLeftCurrentCall = TRUE;
+ }
+ else if ((getState(participant_id) != STATE_LEFT))
+ {
+ setState(item, STATE_INVITED);
+ }
+
+/*
+ // If there is already a started timer for the current panel don't do anything.
+ bool no_timer_for_current_panel = true;
+ if (mTimersMap.size() > 0)
+ {
+ timers_map::iterator found_it = mTimersMap.find(participant_id);
+ if (found_it != mTimersMap.end())
+ {
+ no_timer_for_current_panel = false;
+ }
+ }
+
+ if (no_timer_for_current_panel)
+ {
+ // Starting a timer to remove an avatar row panel after timeout
+ // *TODO Make the timeout period adjustable
+ mTimersMap.insert(timer_pair(participant_id, new LLAvatarRowRemoveTimer(this->getHandle(), 10, participant_id)));
+ }
+*/
+ }
+ }
+
+}
+
+void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
+{
+ setState(item->getAvatarId(), state);
+
+ LLStyle::Params speaker_style;
+ LLFontDescriptor new_desc(speaker_style.font()->getFontDesc());
+
+ switch (state)
+ {
+ case STATE_INVITED:
+// status_str = "INVITED"; // *TODO: localize
+ new_desc.setStyle(LLFontGL::NORMAL);
+ break;
+ case STATE_JOINED:
+// status_str = "JOINED"; // *TODO: localize
+ new_desc.setStyle(LLFontGL::NORMAL);
+ break;
+ case STATE_LEFT:
+ {
+ // status_str = "HAS LEFT CALL"; // *TODO: localize
+ new_desc.setStyle(LLFontGL::ITALIC);
+
+ }
+ break;
+ default:
+ llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl;
+ break;
+ }
+
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+ speaker_style.font = new_font;
+ item->setStyle(speaker_style);
+
+// if ()
+ {
+ // found speaker is in voice, mark him as online
+ item->setOnline(STATE_JOINED == state);
+ }
+}
+
//EOF
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index ac45e283eb..21fba433c6 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -38,6 +38,7 @@
#include "llvoiceclient.h"
class LLAvatarList;
+class LLAvatarListItem;
class LLNonAvatarCaller;
class LLOutputMonitorCtrl;
class LLParticipantList;
@@ -81,6 +82,16 @@ private:
VC_PEER_TO_PEER
}EVoiceControls;
+ typedef enum e_speaker_state
+ {
+ STATE_UNKNOWN,
+ STATE_INVITED,
+ STATE_JOINED,
+ STATE_LEFT,
+ } ESpeakerState;
+
+ typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t;
+
void leaveCall();
/**
@@ -95,7 +106,7 @@ private:
* Refreshes participant list according to current Voice Channel
*/
void refreshPartisipantList();
-
+ void onAvatarListRefreshed();
void updateTitle();
@@ -103,7 +114,24 @@ private:
void setModeratorMutedVoice(bool moderator_muted);
void updateAgentModeratorState();
+ void initParticipantsVoiceState();
+ void updateParticipantsVoiceState();
+
+ void setState(LLAvatarListItem* item, ESpeakerState state);
+ void setState(const LLUUID& speaker_id, ESpeakerState state)
+ {
+ lldebugs << "Storing state: " << speaker_id << ", " << state << llendl;
+ mSpeakerStateMap[speaker_id] = state;
+ }
+
+ ESpeakerState getState(const LLUUID& speaker_id)
+ {
+ lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl;
+
+ return mSpeakerStateMap[speaker_id];
+ }
private:
+ speaker_state_map_t mSpeakerStateMap;
LLSpeakerMgr* mSpeakerManager;
LLParticipantList* mPaticipants;
LLAvatarList* mAvatarList;
@@ -112,6 +140,11 @@ private:
LLPanel* mAgentPanel;
LLOutputMonitorCtrl* mSpeakingIndicator;
bool mIsModeratorMutedVoice;
+
+ bool mInitParticipantsVoiceState;
+
+ boost::signals2::connection mAvatarListRefreshConnection;
+
};
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index dfe0b504bd..5941487c7d 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -208,27 +208,6 @@ LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
return mSortOrder;
}
-void LLParticipantList::refreshVoiceState()
-{
- LLSpeakerMgr::speaker_list_t speakers;
- mSpeakerMgr->getSpeakerList(&speakers, TRUE);
-
- for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin();
- iter != speakers.end(); ++iter)
- {
- LLSpeaker* speakerp = (*iter).get();
- const LLUUID& speaker_id = speakerp->mID;
- LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(speaker_id));
- if ( item )
- {
- // if voice is disabled for this speaker show non voice speakers as disabled
- bool is_in_voice = speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE
- && speakerp->mStatus != LLSpeaker::STATUS_MUTED;
- item->setOnline(!is_in_voice);
- }
- }
-}
-
void LLParticipantList::updateRecentSpeakersOrder()
{
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index 515529452b..c4eb180917 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -60,12 +60,6 @@ class LLParticipantList
EParticipantSortOrder getSortOrder();
/**
- * Refreshes participants to display ones not in voice as disabled.
- * TODO: mantipov: probably should be moved into derived class for LLFloaterCall
- */
- void refreshVoiceState();
-
- /**
* Refreshes the participant list if it's in sort by recent speaker order.
*/
void updateRecentSpeakersOrder();