Work on normal task EXT-2214 Refactor IM Control Panels
-- replaced functionality to remove speacker from the list via Event timer. -- removed calling of LLSpeakerMgr::update from LLPanelGroupControlPanel::draw() (group text chat) For now list is updated when it is need. --HG-- branch : product-enginemaster
parent
d18c46bc15
commit
1a8325f4dc
|
|
@ -10070,6 +10070,18 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>SpeakerParticipantRemoveDelay</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Timeout to remove participants who is not in channel before removed from list of active speakers (text/voice chat)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>10.0</real>
|
||||
</map>
|
||||
|
||||
<key>UseStartScreen</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -264,9 +264,6 @@ LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
|
|||
// virtual
|
||||
void LLPanelGroupControlPanel::draw()
|
||||
{
|
||||
//Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update()
|
||||
//so we need update it to raise needed event
|
||||
mSpeakerManager->update(true);
|
||||
// Need to resort the participant list if it's in sort by recent speaker order.
|
||||
if (mParticipantList)
|
||||
mParticipantList->updateRecentSpeakersOrder();
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
#include "llvoavatar.h"
|
||||
#include "llworld.h"
|
||||
|
||||
const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
|
||||
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
|
||||
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
|
||||
|
||||
|
|
@ -73,8 +72,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy
|
|||
}
|
||||
|
||||
gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
|
||||
|
||||
mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -164,6 +161,89 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
|
|||
return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
|
||||
}
|
||||
|
||||
LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id)
|
||||
: LLEventTimer(action_period)
|
||||
, mActionCallback(action_cb)
|
||||
, mSpeakerId(speaker_id)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLSpeakerActionTimer::tick()
|
||||
{
|
||||
if (mActionCallback)
|
||||
{
|
||||
return (BOOL)mActionCallback(mSpeakerId);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
|
||||
: mActionCallback(action_cb)
|
||||
, mActionDelay(action_delay)
|
||||
{
|
||||
}
|
||||
|
||||
LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage()
|
||||
{
|
||||
removeAllTimers();
|
||||
}
|
||||
|
||||
void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id)
|
||||
{
|
||||
bool not_found = true;
|
||||
if (mActionTimersMap.size() > 0)
|
||||
{
|
||||
not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end();
|
||||
}
|
||||
|
||||
// If there is already a started timer for the passed UUID don't do anything.
|
||||
if (not_found)
|
||||
{
|
||||
// Starting a timer to remove an participant after delay is completed
|
||||
mActionTimersMap.insert(LLSpeakerActionTimer::action_value_t(speaker_id,
|
||||
new LLSpeakerActionTimer(
|
||||
boost::bind(&LLSpeakersDelayActionsStorage::onTimerActionCallback, this, _1),
|
||||
mActionDelay, speaker_id)));
|
||||
}
|
||||
}
|
||||
|
||||
void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
|
||||
{
|
||||
if (mActionTimersMap.size() == 0) return;
|
||||
|
||||
LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id);
|
||||
|
||||
if (it_speaker != mActionTimersMap.end())
|
||||
{
|
||||
delete it_speaker->second;
|
||||
mActionTimersMap.erase(it_speaker);
|
||||
}
|
||||
}
|
||||
|
||||
void LLSpeakersDelayActionsStorage::removeAllTimers()
|
||||
{
|
||||
LLSpeakerActionTimer::action_timer_iter_t iter = mActionTimersMap.begin();
|
||||
for (; iter != mActionTimersMap.end(); ++iter)
|
||||
{
|
||||
delete iter->second;
|
||||
}
|
||||
mActionTimersMap.clear();
|
||||
}
|
||||
|
||||
bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id)
|
||||
{
|
||||
unsetActionTimer(speaker_id);
|
||||
|
||||
if (mActionCallback)
|
||||
{
|
||||
mActionCallback(speaker_id);
|
||||
}
|
||||
|
||||
// do not return true to avoid deleting of an timer twice:
|
||||
// in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLSpeakerMgr
|
||||
|
|
@ -172,10 +252,14 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
|
|||
LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
|
||||
mVoiceChannel(channelp)
|
||||
{
|
||||
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
|
||||
|
||||
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
|
||||
}
|
||||
|
||||
LLSpeakerMgr::~LLSpeakerMgr()
|
||||
{
|
||||
delete mSpeakerDelayRemover;
|
||||
}
|
||||
|
||||
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
|
||||
|
|
@ -198,7 +282,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
|
|||
{
|
||||
// keep highest priority status (lowest value) instead of overriding current value
|
||||
speakerp->mStatus = llmin(speakerp->mStatus, status);
|
||||
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
|
||||
// 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
|
||||
|
|
@ -210,6 +293,8 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
|
|||
}
|
||||
}
|
||||
|
||||
mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
|
||||
|
||||
return speakerp;
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +399,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||
S32 sort_index = 0;
|
||||
speaker_list_t::iterator sorted_speaker_it;
|
||||
for(sorted_speaker_it = mSpeakersSorted.begin();
|
||||
sorted_speaker_it != mSpeakersSorted.end(); )
|
||||
sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
|
||||
{
|
||||
LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
|
||||
|
||||
|
|
@ -327,19 +412,6 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||
|
||||
// stuff sort ordinal into speaker so the ui can sort by this value
|
||||
speakerp->mSortIndex = sort_index++;
|
||||
|
||||
// remove speakers that have been gone too long
|
||||
if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
|
||||
{
|
||||
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
|
||||
|
||||
mSpeakers.erase(speakerp->mID);
|
||||
sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++sorted_speaker_it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -363,6 +435,35 @@ void LLSpeakerMgr::updateSpeakerList()
|
|||
}
|
||||
}
|
||||
|
||||
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
|
||||
{
|
||||
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
|
||||
speakerp->mDotColor = INACTIVE_COLOR;
|
||||
mSpeakerDelayRemover->setActionTimer(speakerp->mID);
|
||||
}
|
||||
|
||||
bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)
|
||||
{
|
||||
mSpeakers.erase(speaker_id);
|
||||
|
||||
speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin();
|
||||
|
||||
for(; sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
|
||||
{
|
||||
if (speaker_id == (*sorted_speaker_it)->mID)
|
||||
{
|
||||
mSpeakersSorted.erase(sorted_speaker_it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");
|
||||
|
||||
update(TRUE);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
|
||||
{
|
||||
//In some conditions map causes crash if it is empty(Windows only), adding check (EK)
|
||||
|
|
@ -511,9 +612,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||
{
|
||||
if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
|
||||
{
|
||||
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
|
||||
speakerp->mDotColor = INACTIVE_COLOR;
|
||||
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
|
||||
setSpeakerNotInChannel(speakerp);
|
||||
}
|
||||
else if (agent_data["transition"].asString() == "ENTER")
|
||||
{
|
||||
|
|
@ -563,9 +662,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||
std::string agent_transition = update_it->second.asString();
|
||||
if (agent_transition == "LEAVE" && speakerp.notNull())
|
||||
{
|
||||
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
|
||||
speakerp->mDotColor = INACTIVE_COLOR;
|
||||
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
|
||||
setSpeakerNotInChannel(speakerp);
|
||||
}
|
||||
else if ( agent_transition == "ENTER")
|
||||
{
|
||||
|
|
@ -734,12 +831,13 @@ void LLActiveSpeakerMgr::updateSpeakerList()
|
|||
mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
|
||||
|
||||
// always populate from active voice channel
|
||||
if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
|
||||
if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false
|
||||
{
|
||||
fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
|
||||
mSpeakers.clear();
|
||||
mSpeakersSorted.clear();
|
||||
mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
|
||||
mSpeakerDelayRemover->removeAllTimers();
|
||||
}
|
||||
LLSpeakerMgr::updateSpeakerList();
|
||||
|
||||
|
|
@ -800,9 +898,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
|
|||
LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
|
||||
if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
|
||||
{
|
||||
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
|
||||
speakerp->mDotColor = INACTIVE_COLOR;
|
||||
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
|
||||
setSpeakerNotInChannel(speakerp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ public:
|
|||
F32 mLastSpokeTime; // timestamp when this speaker last spoke
|
||||
F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
|
||||
std::string mDisplayName; // cache user name for this speaker
|
||||
LLFrameTimer mActivityTimer; // time out speakers when they are not part of current voice channel
|
||||
BOOL mHasSpoken; // has this speaker said anything this session?
|
||||
BOOL mHasLeftCurrentCall; // has this speaker left the current voice call?
|
||||
LLColor4 mDotColor;
|
||||
|
|
@ -120,6 +119,92 @@ private:
|
|||
const LLUUID& mSpeakerID;
|
||||
};
|
||||
|
||||
/**
|
||||
* class LLSpeakerActionTimer
|
||||
*
|
||||
* Implements a timer that calls stored callback action for stored speaker after passed period.
|
||||
*
|
||||
* Action is called until callback returns "true".
|
||||
* In this case the timer will be removed via LLEventTimer::updateClass().
|
||||
* Otherwise it should be deleted manually in place where it is used.
|
||||
* If action callback is not set timer will tick only once and deleted.
|
||||
*/
|
||||
class LLSpeakerActionTimer : public LLEventTimer
|
||||
{
|
||||
public:
|
||||
typedef boost::function<bool(const LLUUID&)> action_callback_t;
|
||||
typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
|
||||
typedef action_timers_map_t::value_type action_value_t;
|
||||
typedef action_timers_map_t::const_iterator action_timer_const_iter_t;
|
||||
typedef action_timers_map_t::iterator action_timer_iter_t;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param action_cb - callback which will be called each time after passed action period.
|
||||
* @param action_period - time in seconds timer should tick.
|
||||
* @param speaker_id - LLUUID of speaker which will be passed into action callback.
|
||||
*/
|
||||
LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id);
|
||||
virtual ~LLSpeakerActionTimer() {};
|
||||
|
||||
/**
|
||||
* Implements timer "tick".
|
||||
*
|
||||
* If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass().
|
||||
*/
|
||||
virtual BOOL tick();
|
||||
|
||||
private:
|
||||
action_callback_t mActionCallback;
|
||||
LLUUID mSpeakerId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a functionality to store actions for speakers with delay.
|
||||
* Is based on LLSpeakerActionTimer.
|
||||
*/
|
||||
class LLSpeakersDelayActionsStorage
|
||||
{
|
||||
public:
|
||||
LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay);
|
||||
~LLSpeakersDelayActionsStorage();
|
||||
|
||||
/**
|
||||
* Sets new LLSpeakerActionTimer with passed speaker UUID.
|
||||
*/
|
||||
void setActionTimer(const LLUUID& speaker_id);
|
||||
|
||||
/**
|
||||
* Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it.
|
||||
*
|
||||
* @see onTimerActionCallback()
|
||||
*/
|
||||
void unsetActionTimer(const LLUUID& speaker_id);
|
||||
|
||||
void removeAllTimers();
|
||||
private:
|
||||
/**
|
||||
* Callback of the each instance of LLSpeakerActionTimer.
|
||||
*
|
||||
* Unsets an appropriate timer instance and calls action callback for specified speacker_id.
|
||||
* It always returns false to not use LLEventTimer::updateClass functionality of timer deleting.
|
||||
*
|
||||
* @see unsetActionTimer()
|
||||
*/
|
||||
bool onTimerActionCallback(const LLUUID& speaker_id);
|
||||
|
||||
LLSpeakerActionTimer::action_timers_map_t mActionTimersMap;
|
||||
LLSpeakerActionTimer::action_callback_t mActionCallback;
|
||||
|
||||
/**
|
||||
* Delay to call action callback for speakers after timer was set.
|
||||
*/
|
||||
F32 mActionDelay;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class LLSpeakerMgr : public LLOldEvents::LLObservable
|
||||
{
|
||||
public:
|
||||
|
|
@ -144,6 +229,8 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void updateSpeakerList();
|
||||
void setSpeakerNotInChannel(LLSpeaker* speackerp);
|
||||
bool removeSpeaker(const LLUUID& speaker_id);
|
||||
|
||||
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
|
||||
speaker_map_t mSpeakers;
|
||||
|
|
@ -151,6 +238,11 @@ protected:
|
|||
speaker_list_t mSpeakersSorted;
|
||||
LLFrameTimer mSpeechTimer;
|
||||
LLVoiceChannel* mVoiceChannel;
|
||||
|
||||
/**
|
||||
* time out speakers when they are not part of current session
|
||||
*/
|
||||
LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
|
||||
};
|
||||
|
||||
class LLIMSpeakerMgr : public LLSpeakerMgr
|
||||
|
|
|
|||
Loading…
Reference in New Issue