summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llavatarlist.cpp75
-rw-r--r--indra/newview/llavatarlist.h25
-rw-r--r--indra/newview/llavatarlistitem.cpp12
-rw-r--r--indra/newview/llavatarlistitem.h2
-rw-r--r--indra/newview/llparticipantlist.cpp210
-rw-r--r--indra/newview/llparticipantlist.h5
-rw-r--r--indra/newview/llspeakers.h8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
8 files changed, 332 insertions, 7 deletions
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 407c5b6153..c7a5691d70 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -32,13 +32,18 @@
#include "llviewerprecompiledheaders.h"
+// common
+#include "lltrans.h"
+
#include "llavatarlist.h"
#include "llagentdata.h" // for comparator
// newview
+#include "llavatariconctrl.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llcachename.h"
#include "llrecentpeople.h"
+#include "lltextutil.h"
#include "lluuid.h"
#include "llvoiceclient.h"
#include "llviewercontrol.h" // for gSavedSettings
@@ -193,6 +198,18 @@ void LLAvatarList::setDirty(bool val /*= true*/, bool force_refresh /*= false*/)
}
}
+void LLAvatarList::addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name)
+{
+ LL_DEBUGS("Avaline") << "Adding avaline item into the list: " << item_name << "|" << item_id << ", session: " << session_id << LL_ENDL;
+ LLAvalineListItem* item = new LLAvalineListItem;
+ item->setAvatarId(item_id, session_id, true, false);
+ item->setName(item_name);
+
+ addItem(item, item_id);
+ mIDs.push_back(item_id);
+ sort();
+}
+
//////////////////////////////////////////////////////////////////////////
// PROTECTED SECTION
//////////////////////////////////////////////////////////////////////////
@@ -471,3 +488,61 @@ bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_
}
return LLAvatarItemNameComparator::doCompare(avatar_item1,avatar_item2);
}
+
+/************************************************************************/
+/* class LLAvalineListItem */
+/************************************************************************/
+LLAvalineListItem::LLAvalineListItem(bool hide_number/* = true*/) : LLAvatarListItem(false)
+, mIsHideNumber(hide_number)
+{
+ // should not use buildPanel from the base class to ensure LLAvalineListItem::postBuild is called.
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
+}
+
+BOOL LLAvalineListItem::postBuild()
+{
+ BOOL rv = LLAvatarListItem::postBuild();
+
+ if (rv)
+ {
+ setOnline(true);
+ showLastInteractionTime(false);
+ setShowProfileBtn(false);
+ setShowInfoBtn(false);
+ mAvatarIcon->setValue("Avaline_Icon");
+ mAvatarIcon->setToolTip(std::string(""));
+ }
+ return rv;
+}
+
+// to work correctly this method should be called AFTER setAvatarId for avaline callers with hidden phone number
+void LLAvalineListItem::setName(const std::string& name)
+{
+ if (mIsHideNumber)
+ {
+ static U32 order = 0;
+ typedef std::map<LLUUID, U32> avaline_callers_nums_t;
+ static avaline_callers_nums_t mAvalineCallersNums;
+
+ llassert(getAvatarId() != LLUUID::null);
+
+ const LLUUID &uuid = getAvatarId();
+
+ if (mAvalineCallersNums.find(uuid) == mAvalineCallersNums.end())
+ {
+ mAvalineCallersNums[uuid] = ++order;
+ LL_DEBUGS("Avaline") << "Set name for new avaline caller: " << uuid << ", order: " << order << LL_ENDL;
+ }
+ LLStringUtil::format_map_t args;
+ args["[ORDER]"] = llformat("%u", mAvalineCallersNums[uuid]);
+ std::string hidden_name = LLTrans::getString("AvalineCaller", args);
+
+ LL_DEBUGS("Avaline") << "Avaline caller: " << uuid << ", name: " << hidden_name << LL_ENDL;
+ LLAvatarListItem::setName(hidden_name);
+ }
+ else
+ {
+ const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
+ LLAvatarListItem::setName(formatted_phone);
+ }
+}
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index 0203617867..528f796b8b 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -96,6 +96,8 @@ public:
virtual S32 notifyParent(const LLSD& info);
+ void addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name);
+
protected:
void refresh();
@@ -175,4 +177,27 @@ protected:
virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
};
+/**
+ * Represents Avaline caller in Avatar list in Voice Control Panel and group chats.
+ */
+class LLAvalineListItem : public LLAvatarListItem
+{
+public:
+
+ /**
+ * Constructor
+ *
+ * @param hide_number - flag indicating if number should be hidden.
+ * In this case It will be shown as "Avaline Caller 1", "Avaline Caller 1", etc.
+ */
+ LLAvalineListItem(bool hide_number = true);
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void setName(const std::string& name);
+
+private:
+ bool mIsHideNumber;
+};
+
#endif // LL_LLAVATARLIST_H
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 44f88cce29..2a51eeacfc 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -212,21 +212,25 @@ void LLAvatarListItem::setState(EItemState item_style)
mAvatarIcon->setColor(item_icon_color_map[item_style]);
}
-void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes)
+void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes/* = false*/, bool is_resident/* = true*/)
{
if (mAvatarId.notNull())
LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
mAvatarId = id;
- mAvatarIcon->setValue(id);
mSpeakingIndicator->setSpeakerId(id, session_id);
// We'll be notified on avatar online status changes
if (!ignore_status_changes && mAvatarId.notNull())
LLAvatarTracker::instance().addParticularFriendObserver(mAvatarId, this);
- // Set avatar name.
- gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
+ if (is_resident)
+ {
+ mAvatarIcon->setValue(id);
+
+ // Set avatar name.
+ gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
+ }
}
void LLAvatarListItem::showLastInteractionTime(bool show)
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index 2db6484a30..3ba2c7a3e3 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -100,7 +100,7 @@ public:
void setName(const std::string& name);
void setHighlight(const std::string& highlight);
void setState(EItemState item_style);
- void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false);
+ void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false, bool is_resident = true);
void setLastInteractionTime(U32 secs_since);
//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
void setShowProfileBtn(bool show);
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 026be882ed..53f92f7ad1 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -50,6 +50,145 @@
static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR;
+// See EXT-4301.
+/**
+ * class LLAvalineUpdater - observe the list of voice participants in session and check
+ * presence of Avaline Callers among them.
+ *
+ * LLAvalineUpdater is a LLVoiceClientParticipantObserver. It provides two kinds of validation:
+ * - whether Avaline caller presence among participants;
+ * - whether watched Avaline caller still exists in voice channel.
+ * Both validations have callbacks which will notify subscriber if any of event occur.
+ *
+ * @see findAvalineCaller()
+ * @see checkIfAvalineCallersExist()
+ */
+class LLAvalineUpdater : public LLVoiceClientParticipantObserver
+{
+public:
+ typedef boost::function<void(const LLUUID& speaker_id)> process_avaline_callback_t;
+
+ LLAvalineUpdater(process_avaline_callback_t found_cb, process_avaline_callback_t removed_cb)
+ : mAvalineFoundCallback(found_cb)
+ , mAvalineRemovedCallback(removed_cb)
+ {
+ LLVoiceClient::getInstance()->addObserver(this);
+ }
+ ~LLAvalineUpdater()
+ {
+ if (LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver(this);
+ }
+ }
+
+ /**
+ * Adds UUID of Avaline caller to watch.
+ *
+ * @see checkIfAvalineCallersExist().
+ */
+ void watchAvalineCaller(const LLUUID& avaline_caller_id)
+ {
+ mAvalineCallers.insert(avaline_caller_id);
+ }
+
+ void onChange()
+ {
+ uuid_set_t participant_uuids;
+ LLVoiceClient::getInstance()->getParticipantsUUIDSet(participant_uuids);
+
+
+ // check whether Avaline caller exists among voice participants
+ // and notify Participant List
+ findAvalineCaller(participant_uuids);
+
+ // check whether watched Avaline callers still present among voice participant
+ // and remove if absents.
+ checkIfAvalineCallersExist(participant_uuids);
+ }
+
+private:
+ typedef std::set<LLUUID> uuid_set_t;
+
+ /**
+ * Finds Avaline callers among voice participants and calls mAvalineFoundCallback.
+ *
+ * When Avatar is in group call with Avaline caller and then ends call Avaline caller stays
+ * in Group Chat floater (exists in LLSpeakerMgr). If Avatar starts call with that group again
+ * Avaline caller is added to voice channel AFTER Avatar is connected to group call.
+ * But Voice Control Panel (VCP) is filled from session LLSpeakerMgr and there is no information
+ * if a speaker is Avaline caller.
+ *
+ * In this case this speaker is created as avatar and will be recreated when it appears in
+ * Avatar's Voice session.
+ *
+ * @see LLParticipantList::onAvalineCallerFound()
+ */
+ void findAvalineCaller(const uuid_set_t& participant_uuids)
+ {
+ uuid_set_t::const_iterator it = participant_uuids.begin(), it_end = participant_uuids.end();
+
+ for(; it != it_end; ++it)
+ {
+ const LLUUID& participant_id = *it;
+ if (!LLVoiceClient::getInstance()->isParticipantAvatar(participant_id))
+ {
+ LL_DEBUGS("Avaline") << "Avaline caller found among voice participants: " << participant_id << LL_ENDL;
+
+ if (mAvalineFoundCallback)
+ {
+ mAvalineFoundCallback(participant_id);
+ }
+ }
+ }
+ }
+
+ /**
+ * Finds Avaline callers which are not anymore among voice participants and calls mAvalineRemovedCallback.
+ *
+ * The problem is when Avaline caller ends a call it is removed from Voice Client session but
+ * still exists in LLSpeakerMgr. Server does not send such information.
+ * This method implements a HUCK to notify subscribers that watched Avaline callers by class
+ * are not anymore in the call.
+ *
+ * @see LLParticipantList::onAvalineCallerRemoved()
+ */
+ void checkIfAvalineCallersExist(const uuid_set_t& participant_uuids)
+ {
+ uuid_set_t::iterator it = mAvalineCallers.begin();
+ uuid_set_t::const_iterator participants_it_end = participant_uuids.end();
+
+ while (it != mAvalineCallers.end())
+ {
+ const LLUUID participant_id = *it;
+ LL_DEBUGS("Avaline") << "Check avaline caller: " << participant_id << LL_ENDL;
+ bool not_found = participant_uuids.find(participant_id) == participants_it_end;
+ if (not_found)
+ {
+ LL_DEBUGS("Avaline") << "Watched Avaline caller is not found among voice participants: " << participant_id << LL_ENDL;
+
+ // notify Participant List
+ if (mAvalineRemovedCallback)
+ {
+ mAvalineRemovedCallback(participant_id);
+ }
+
+ // remove from the watch list
+ mAvalineCallers.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ }
+
+ process_avaline_callback_t mAvalineFoundCallback;
+ process_avaline_callback_t mAvalineRemovedCallback;
+
+ uuid_set_t mAvalineCallers;
+};
+
LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/,
bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/):
mSpeakerMgr(data_source),
@@ -59,6 +198,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
, mExcludeAgent(exclude_agent)
, mValidateSpeakerCallback(NULL)
{
+ mAvalineUpdater = new LLAvalineUpdater(boost::bind(&LLParticipantList::onAvalineCallerFound, this, _1),
+ boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1));
+
mSpeakerAddListener = new SpeakerAddListener(*this);
mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
mSpeakerClearListener = new SpeakerClearListener(*this);
@@ -137,6 +279,9 @@ LLParticipantList::~LLParticipantList()
}
mAvatarList->setContextMenu(NULL);
+ mAvatarList->setComparator(NULL);
+
+ delete mAvalineUpdater;
}
void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
@@ -210,6 +355,55 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
}
}
+/*
+Seems this method is not necessary after onAvalineCallerRemoved was implemented;
+
+It does nothing because list item is always created with correct class type for Avaline caller.
+For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client
+session.
+This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call.
+
+Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself.
+Asked in EXT-4301.
+*/
+void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id)
+{
+ LLPanel* item = mAvatarList->getItemByValue(participant_id);
+
+ if (NULL == item)
+ {
+ LL_WARNS("Avaline") << "Something wrong. Unable to find item for: " << participant_id << LL_ENDL;
+ return;
+ }
+
+ if (typeid(*item) == typeid(LLAvalineListItem))
+ {
+ LL_DEBUGS("Avaline") << "Avaline caller has already correct class type for: " << participant_id << LL_ENDL;
+ // item representing an Avaline caller has a correct type already.
+ return;
+ }
+
+ LL_DEBUGS("Avaline") << "remove item from the list and re-add it: " << participant_id << LL_ENDL;
+
+ // remove UUID from LLAvatarList::mIDs to be able add it again.
+ uuid_vec_t& ids = mAvatarList->getIDs();
+ uuid_vec_t::iterator pos = std::find(ids.begin(), ids.end(), participant_id);
+ ids.erase(pos);
+
+ // remove item directly
+ mAvatarList->removeItem(item);
+
+ // re-add avaline caller with a correct class instance.
+ addAvatarIDExceptAgent(participant_id);
+}
+
+void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id)
+{
+ LL_DEBUGS("Avaline") << "Removing avaline caller from the list: " << participant_id << LL_ENDL;
+
+ mSpeakerMgr->removeAvalineSpeaker(participant_id);
+}
+
void LLParticipantList::setSortOrder(EParticipantSortOrder order)
{
if ( mSortOrder != order )
@@ -355,8 +549,20 @@ void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
if (mExcludeAgent && gAgent.getID() == avatar_id) return;
if (mAvatarList->contains(avatar_id)) return;
- mAvatarList->getIDs().push_back(avatar_id);
- mAvatarList->setDirty();
+ bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(avatar_id);
+
+ if (is_avatar)
+ {
+ mAvatarList->getIDs().push_back(avatar_id);
+ mAvatarList->setDirty();
+ }
+ else
+ {
+ LLVoiceClient::participantState *participant = LLVoiceClient::getInstance()->findParticipantByID(avatar_id);
+
+ mAvatarList->addAvalineItem(avatar_id, mSpeakerMgr->getSessionID(), participant ? participant->mAccountName : LLTrans::getString("AvatarNameWaiting"));
+ mAvalineUpdater->watchAvalineCaller(avatar_id);
+ }
adjustParticipant(avatar_id);
}
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index 953dff4551..9e5a2cbc1f 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -38,6 +38,7 @@
class LLSpeakerMgr;
class LLAvatarList;
class LLUICtrl;
+class LLAvalineUpdater;
class LLParticipantList
{
@@ -235,6 +236,9 @@ class LLParticipantList
void onAvatarListDoubleClicked(LLUICtrl* ctrl);
void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
+ void onAvalineCallerFound(const LLUUID& participant_id);
+ void onAvalineCallerRemoved(const LLUUID& participant_id);
+
/**
* Adjusts passed participant to work properly.
*
@@ -272,4 +276,5 @@ class LLParticipantList
LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
validate_speaker_callback_t mValidateSpeakerCallback;
+ LLAvalineUpdater* mAvalineUpdater;
};
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index b924fb2f2c..2bb160b7ce 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -234,6 +234,14 @@ public:
LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
const LLUUID getSessionID();
+ /**
+ * Removes avaline speaker.
+ *
+ * This is a HACK due to server does not send information that Avaline caller ends call.
+ * It can be removed when server is updated. See EXT-4301 for details
+ */
+ bool removeAvalineSpeaker(const LLUUID& speaker_id) { return removeSpeaker(speaker_id); }
+
protected:
virtual void updateSpeakerList();
void setSpeakerNotInChannel(LLSpeaker* speackerp);
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b0bf51c214..813f59ff89 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -148,6 +148,8 @@
<!-- Group name: text shown for LLUUID::null -->
<string name="GroupNameNone">(none)</string>
+ <string name="AvalineCaller">Avaline Caller [ORDER]</string>
+
<!-- Asset errors. Used in llassetstorage.cpp, translation from error code to error message. -->
<string name="AssetErrorNone">No error</string>
<string name="AssetErrorRequestFailed">Asset request: failed</string>