master
Brad Payne (Vir Linden) 2009-12-23 15:17:05 -05:00
commit ce86efac3d
25 changed files with 478 additions and 131 deletions

View File

@ -139,6 +139,9 @@ public:
/// Get information about a specific Callable
LLSD getMetadata(const std::string& name) const;
/// Retrieve the LLSD key we use for one-arg <tt>operator()</tt> method
std::string getDispatchKey() const { return mKey; }
private:
template <class CLASS, typename METHOD>
void addMethod(const std::string& name, const std::string& desc,

View File

@ -135,7 +135,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
// determine which style flags need to be added programmatically by striping off the
// determine which style flags need to be added programmatically by stripping off the
// style bits that are drawn by the underlying Freetype font
U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();

View File

@ -414,6 +414,16 @@ void LLLayoutStack::updatePanelAutoResize(const std::string& panel_name, BOOL au
}
}
void LLLayoutStack::setPanelUserResize(const std::string& panel_name, BOOL user_resize)
{
LayoutPanel* panel = findEmbeddedPanelByName(panel_name);
if (panel)
{
panel->mUserResize = user_resize;
}
}
bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_widthp, S32* min_heightp)
{
LayoutPanel* panel = findEmbeddedPanelByName(panel_name);

View File

@ -80,6 +80,7 @@ public:
S32 getNumPanels() { return mPanels.size(); }
void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
void setPanelUserResize(const std::string& panel_name, BOOL user_resize);
/**
* Gets minimal width and/or height of the specified by name panel.

View File

@ -188,9 +188,10 @@ public:
LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
if (channelptr)
{
// Try connecting at the front of the 'changed' signal. That way
// we shouldn't get starved by preceding listeners.
channelptr->connectAtFrontChanged(boost::bind(&Forwarder::handle, this, _1));
// Insert our processing as a "passed filter" listener. This way
// we get to run before all the "changed" listeners, and we get to
// swipe it (hide it from the other listeners) if desired.
channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1));
}
}
@ -251,6 +252,7 @@ bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
if (notification["sigtype"].asString() == "delete")
{
LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
// let other listeners see the "delete" operation
return false;
}
LLNotificationPtr note(mNotifications.find(notification["id"]));
@ -262,6 +264,8 @@ bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
if (! matchType(mTypes, note->getType()))
{
LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
// We're not supposed to intercept this particular notification. Let
// other listeners process it.
return false;
}
LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
@ -282,7 +286,11 @@ bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
mNotifications.cancel(note);
}
}
return false; // let other listeners get same notification
// If we've auto-responded to this notification, then it's going to be
// deleted. Other listeners would get the change operation, try to look it
// up and be baffled by lookup failure. So when we auto-respond, suppress
// this notification: don't pass it to other listeners.
return mRespond;
}
bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
@ -314,7 +322,7 @@ bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std
LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
{
LLSD notificationInfo(note->asLLSD());
// For some reason the following aren't included in asLLSD().
// For some reason the following aren't included in LLNotification::asLLSD().
notificationInfo["summary"] = note->summarize();
notificationInfo["id"] = note->id();
notificationInfo["type"] = note->getType();

View File

@ -842,7 +842,7 @@ BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)
{
// Did we just click on a link?
if (cur_segment->getStyle()
&& cur_segment->getStyle()->isLink())
&& cur_segment->getStyle()->isLink())
{
// *TODO: send URL here?
mURLClickSignal(this, LLSD() );
@ -1477,7 +1477,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
}
}
void LLTextBase::setText(const LLStringExplicit &utf8str ,const LLStyle::Params& input_params)
void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
// clear out the existing text and segments
getViewModel()->setDisplay(LLWStringUtil::null);
@ -2320,14 +2320,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 end = llmin( selection_start, seg_end );
S32 length = end - start;
font->render(text, start,
rect.mLeft, rect.mTop,
color,
LLFontGL::LEFT, LLFontGL::TOP,
0,
mStyle->getShadowType(),
length, rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
rect.mLeft, rect.mTop,
color,
LLFontGL::LEFT, LLFontGL::TOP,
LLFontGL::NORMAL,
mStyle->getShadowType(),
length, rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
}
rect.mLeft = (S32)ceil(right_x);
@ -2339,14 +2339,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 length = end - start;
font->render(text, start,
rect.mLeft, rect.mTop,
LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
LLFontGL::LEFT, LLFontGL::TOP,
0,
LLFontGL::NO_SHADOW,
length, rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
rect.mLeft, rect.mTop,
LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ),
LLFontGL::LEFT, LLFontGL::TOP,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
length, rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
}
rect.mLeft = (S32)ceil(right_x);
if( selection_end < seg_end )
@ -2356,14 +2356,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 end = seg_end;
S32 length = end - start;
font->render(text, start,
rect.mLeft, rect.mTop,
color,
LLFontGL::LEFT, LLFontGL::TOP,
0,
mStyle->getShadowType(),
length, rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
rect.mLeft, rect.mTop,
color,
LLFontGL::LEFT, LLFontGL::TOP,
LLFontGL::NORMAL,
mStyle->getShadowType(),
length, rect.getWidth(),
&right_x,
mEditor.getUseEllipses());
}
return right_x;
}

View File

@ -1397,12 +1397,29 @@ if (WINDOWS)
# be met. I'm looking forward to a source-code split-up project next year that will address this kind of thing.
# In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py
# and have the build deps get tracked *please* tell me about it.
if(LLKDU_LIBRARY)
# Configure a var for llkdu which may not exist for all builds.
set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll)
endif(LLKDU_LIBRARY)
if(USE_GOOGLE_PERFTOOLS)
# Configure a var for tcmalloc location, if used.
# Note the need to specify multiple names explicitly.
set(GOOGLE_PERF_TOOLS_SOURCE
${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll
${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll
)
endif(USE_GOOGLE_PERFTOOLS)
set(COPY_INPUT_DEPENDECIES
# The following commented dependencies are determined at variably at build time. Can't do this here.
#llkdu.dll => llkdu.dll
#${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll
${CMAKE_SOURCE_DIR}/../etc/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
${LLKDU_DLL_SOURCE}
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll
@ -1426,6 +1443,7 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/zlib1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxplatform.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxoal.dll
${GOOGLE_PERF_TOOLS_SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll
@ -1501,7 +1519,7 @@ if (WINDOWS)
if(LLKDU_LIBRARY)
# kdu may not exist!
add_dependencies(${VIEWER_BINARY_NAME} llkdu)
add_dependencies(copy_w_viewer_manifest llkdu)
endif(LLKDU_LIBRARY)
if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)

View File

@ -3585,7 +3585,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]</string>
<string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]</string>
</map>
<key>HighResSnapshot</key>
<map>

View File

@ -157,7 +157,7 @@ Intel Bear Lake .*Intel.*Bear Lake.* 0 0
Intel Broadwater .*Intel.*Broadwater.* 0 0
Intel Brookdale .*Intel.*Brookdale.* 0 0
Intel Cantiga .*Intel.*Cantiga.* 0 0
Intel Eaglelake .*Intel.*Eaglelake.* 0 0
Intel Eaglelake .*Intel.*Eaglelake.* 0 1
Intel Montara .*Intel.*Montara.* 0 0
Intel Springdale .*Intel.*Springdale.* 0 0
Matrox .*Matrox.* 0 0

View File

@ -243,7 +243,6 @@ void LLAvatarActions::startAdhocCall(const std::vector<LLUUID>& ids)
return;
}
// start the call once the session has fully initialized
gIMMgr->autoStartCallOnStartup(session_id);
make_ui_sound("UISndStartIM");

View File

@ -79,6 +79,28 @@ static void* create_non_avatar_caller(void*)
return new LLNonAvatarCaller;
}
LLCallFloater::LLAvatarListItemRemoveTimer::LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id)
: LLEventTimer(period)
, mRemoveCallback(remove_cb)
, mSpeakerId(speaker_id)
{
}
BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()
{
if (mRemoveCallback)
{
mRemoveCallback(mSpeakerId);
}
return TRUE;
}
LLCallFloater::Params::Params()
: voice_left_remove_delay("voice_left_remove_delay", 10)
{
}
LLCallFloater::LLCallFloater(const LLSD& key)
: LLDockableFloater(NULL, false, key)
, mSpeakerManager(NULL)
@ -90,6 +112,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
, mInitParticipantsVoiceState(false)
, mVoiceLeftRemoveDelay(10) // TODO: mantipov: make xml driven
{
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
@ -98,6 +121,8 @@ LLCallFloater::LLCallFloater(const LLSD& key)
LLCallFloater::~LLCallFloater()
{
resetVoiceRemoveTimers();
delete mPaticipants;
mPaticipants = NULL;
@ -149,7 +174,11 @@ void LLCallFloater::draw()
// It should be done only when she joins or leaves voice chat.
// But seems that LLVoiceClientParticipantObserver is not enough to satisfy this requirement.
// *TODO: mantipov: remove from draw()
onChange();
// NOTE: it looks like calling onChange() here is not necessary,
// but sometime it is not called properly from the observable object.
// Seems this is a problem somewhere in Voice Client (LLVoiceClient::participantAddedEvent)
// onChange();
bool is_moderator_muted = gVoiceClient->getIsModeratorMuted(gAgentID);
@ -262,12 +291,28 @@ void LLCallFloater::updateSession()
if (show_me)
{
setVisible(true);
// Workaround(EM): Set current call dialog to front most because
// connect/leaving popups should appear on top of VCP.
// See bug EXT-3628.
LLOutgoingCallDialog* instance =
LLFloaterReg::findTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
if(instance && instance->getVisible())
{
instance->setFrontmost();
}
}
}
}
void LLCallFloater::refreshPartisipantList()
{
// lets forget states from the previous session
// for timers...
resetVoiceRemoveTimers();
// ...and for speaker state
mSpeakerStateMap.clear();
delete mPaticipants;
mPaticipants = NULL;
mAvatarList->clear();
@ -482,28 +527,10 @@ void LLCallFloater::updateParticipantsVoiceState()
std::vector<LLUUID> speakers_list;
// Get a list of participants from VoiceClient
LLVoiceClient::participantMap *map = gVoiceClient->getParticipantList();
if (!map) return;
std::vector<LLUUID> speakers_uuids;
get_voice_participants_uuids(speakers_uuids);
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.
// Updating the status for each participant already in list.
std::vector<LLPanel*> items;
mAvatarList->getItems(items);
std::vector<LLPanel*>::const_iterator
@ -518,14 +545,14 @@ void LLCallFloater::updateParticipantsVoiceState()
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);
std::vector<LLUUID>::iterator speakers_iter = std::find(speakers_uuids.begin(), speakers_uuids.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())
if (speakers_iter != speakers_uuids.end())
{
setState(item, STATE_JOINED);
@ -534,15 +561,15 @@ void LLCallFloater::updateParticipantsVoiceState()
continue;
speaker->mHasLeftCurrentCall = FALSE;
speakers_list.erase(speakers_iter);
speakers_uuids.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 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 ((getState(participant_id) == STATE_JOINED))
{
setState(item, STATE_LEFT);
@ -553,30 +580,13 @@ void LLCallFloater::updateParticipantsVoiceState()
speaker->mHasLeftCurrentCall = TRUE;
}
// If an avatarID is not found in a speakers list from VoiceClient and
// a panel with this ID has a LEFT status this means that this person
// HAS ENTERED session but it is not in voice chat yet. So, set INVITED status
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)));
}
*/
}
}
@ -584,6 +594,19 @@ void LLCallFloater::updateParticipantsVoiceState()
void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
{
// *HACK: mantipov: sometimes such situation is possible while switching to voice channel:
/*
- voice channel is switched to the one user is joining
- participant list is initialized with voice states: agent is in voice
- than such log messages were found (with agent UUID)
- LLVivoxProtocolParser::process_impl: parsing: <Response requestId="22" action="Session.MediaDisconnect.1"><ReturnCode>0</ReturnCode><Results><StatusCode>0</StatusCode><StatusString /></Results><InputXml><Request requestId="22" action="Session.MediaDisconnect.1"><SessionGroupHandle>9</SessionGroupHandle><SessionHandle>12</SessionHandle><Media>Audio</Media></Request></InputXml></Response>
- LLVoiceClient::sessionState::removeParticipant: participant "sip:x2pwNkMbpR_mK4rtB_awASA==@bhr.vivox.com" (da9c0d90-c6e9-47f9-8ae2-bb41fdac0048) removed.
- and than while updating participants voice states agent is marked as HAS LEFT
- next updating of LLVoiceClient state makes agent JOINED
So, lets skip HAS LEFT state for agent's avatar
*/
if (STATE_LEFT == state && item->getAvatarId() == gAgentID) return;
setState(item->getAvatarId(), state);
LLStyle::Params speaker_style;
@ -592,18 +615,16 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
switch (state)
{
case STATE_INVITED:
// status_str = "INVITED"; // *TODO: localize
new_desc.setStyle(LLFontGL::NORMAL);
break;
case STATE_JOINED:
// status_str = "JOINED"; // *TODO: localize
removeVoiceRemoveTimer(item->getAvatarId());
new_desc.setStyle(LLFontGL::NORMAL);
break;
case STATE_LEFT:
{
// status_str = "HAS LEFT CALL"; // *TODO: localize
setVoiceRemoveTimer(item->getAvatarId());
new_desc.setStyle(LLFontGL::ITALIC);
}
break;
default:
@ -622,4 +643,70 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
}
}
void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
// If there is already a started timer for the current panel don't do anything.
bool no_timer_for_current_panel = true;
if (mVoiceLeftTimersMap.size() > 0)
{
timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
if (found_it != mVoiceLeftTimersMap.end())
{
no_timer_for_current_panel = false;
}
}
if (no_timer_for_current_panel)
{
// Starting a timer to remove an avatar row panel after timeout
mVoiceLeftTimersMap.insert(timer_pair(voice_speaker_id,
new LLAvatarListItemRemoveTimer(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), mVoiceLeftRemoveDelay, voice_speaker_id)));
}
}
void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
{
if (mVoiceLeftTimersMap.size() > 0)
{
mVoiceLeftTimersMap.erase(mVoiceLeftTimersMap.find(voice_speaker_id));
}
LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs();
LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id);
if(pos != speaker_uuids.end())
{
speaker_uuids.erase(pos);
mAvatarList->setDirty();
}
}
void LLCallFloater::resetVoiceRemoveTimers()
{
if (mVoiceLeftTimersMap.size() > 0)
{
for (timers_map::iterator iter = mVoiceLeftTimersMap.begin();
iter != mVoiceLeftTimersMap.end(); ++iter)
{
delete iter->second;
}
}
mVoiceLeftTimersMap.clear();
}
void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
// Remove the timer if it has been already started
if (mVoiceLeftTimersMap.size() > 0)
{
timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
if (found_it != mVoiceLeftTimersMap.end())
{
delete found_it->second;
mVoiceLeftTimersMap.erase(found_it);
}
}
}
//EOF

View File

@ -57,6 +57,15 @@ class LLSpeakerMgr;
class LLCallFloater : public LLDockableFloater, LLVoiceClientParticipantObserver
{
public:
struct Params : public LLInitParam::Block<Params, LLDockableFloater::Params>
{
Optional<S32> voice_left_remove_delay;
Params();
};
LOG_CLASS(LLCallFloater);
LLCallFloater(const LLSD& key);
~LLCallFloater();
@ -106,6 +115,13 @@ private:
* Refreshes participant list according to current Voice Channel
*/
void refreshPartisipantList();
/**
* Handles event on avatar list is refreshed after it was marked dirty.
*
* It sets initial participants voice states (once after the first refreshing)
* and updates voice states each time anybody is joined/left voice chat in session.
*/
void onAvatarListRefreshed();
@ -114,7 +130,21 @@ private:
void setModeratorMutedVoice(bool moderator_muted);
void updateAgentModeratorState();
/**
* Sets initial participants voice states in avatar list (Invited, Joined, Has Left).
*
* @see refreshPartisipantList()
* @see onAvatarListRefreshed()
* @see mInitParticipantsVoiceState
*/
void initParticipantsVoiceState();
/**
* Updates participants voice states in avatar list (Invited, Joined, Has Left).
*
* @see onAvatarListRefreshed()
* @see onChanged()
*/
void updateParticipantsVoiceState();
void setState(LLAvatarListItem* item, ESpeakerState state);
@ -130,6 +160,34 @@ private:
return mSpeakerStateMap[speaker_id];
}
/**
* Instantiates new LLAvatarListItemRemoveTimer and adds it into the map if it is not already created.
*
* @param voice_speaker_id LLUUID of Avatar List item to be removed from the list when timer expires.
*/
void setVoiceRemoveTimer(const LLUUID& voice_speaker_id);
/**
* Removes specified by UUID Avatar List item.
*
* @param voice_speaker_id LLUUID of Avatar List item to be removed from the list.
*/
void removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
/**
* Deletes all timers from the list to prevent started timers from ticking after destruction
* and after switching on another voice channel.
*/
void resetVoiceRemoveTimers();
/**
* Removes specified by UUID timer from the map.
*
* @param voice_speaker_id LLUUID of Avatar List item whose timer should be removed from the map.
*/
void removeVoiceRemoveTimer(const LLUUID& voice_speaker_id);
private:
speaker_state_map_t mSpeakerStateMap;
LLSpeakerMgr* mSpeakerManager;
@ -141,10 +199,45 @@ private:
LLOutputMonitorCtrl* mSpeakingIndicator;
bool mIsModeratorMutedVoice;
/**
* Flag indicated that participants voice states should be initialized.
*
* It is used due to Avatar List has delayed refreshing after it content is changed.
* Real initializing is performed when Avatar List is first time refreshed.
*
* @see onAvatarListRefreshed()
* @see initParticipantsVoiceState()
*/
bool mInitParticipantsVoiceState;
boost::signals2::connection mAvatarListRefreshConnection;
/**
* class LLAvatarListItemRemoveTimer
*
* Implements a timer that removes avatar list item of a participant
* who has left the call.
*/
class LLAvatarListItemRemoveTimer : public LLEventTimer
{
public:
typedef boost::function<void(const LLUUID&)> callback_t;
LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id);
virtual ~LLAvatarListItemRemoveTimer() {};
virtual BOOL tick();
private:
callback_t mRemoveCallback;
LLUUID mSpeakerId;
};
typedef std::pair<LLUUID, LLAvatarListItemRemoveTimer*> timer_pair;
typedef std::map<LLUUID, LLAvatarListItemRemoveTimer*> timers_map;
timers_map mVoiceLeftTimersMap;
S32 mVoiceLeftRemoveDelay;
};

View File

@ -138,12 +138,7 @@ void LLGroupActions::startCall(const LLUUID& group_id)
}
// start the call
// *TODO: move this to LLIMMgr?
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
if (session && session->mSessionInitialized)
gIMMgr->startCall(session_id);
else
gIMMgr->autoStartCallOnStartup(session_id);
gIMMgr->autoStartCallOnStartup(session_id);
make_ui_sound("UISndStartIM");
}

View File

@ -45,6 +45,7 @@
#include "llfloaterchat.h"
#include "llfloaterreg.h"
#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container
#include "lllayoutstack.h"
#include "lllineeditor.h"
#include "lllogchat.h"
#include "llpanelimcontrolpanel.h"
@ -56,6 +57,7 @@
#include "llvoicechannel.h"
#include "lltransientfloatermgr.h"
#include "llinventorymodel.h"
#include "llrootview.h"
@ -220,6 +222,12 @@ LLIMFloater::~LLIMFloater()
//virtual
BOOL LLIMFloater::postBuild()
{
// User-resizable control panels in P2P sessions look ugly (EXT-3470).
if (mDialog == IM_NOTHING_SPECIAL || mDialog == IM_SESSION_P2P_INVITE)
{
getChild<LLLayoutStack>("im_panels")->setPanelUserResize("panel_im_control_panel", FALSE);
}
const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
if (other_party_id.notNull())
{
@ -437,6 +445,16 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
void LLIMFloater::getAllowedRect(LLRect& rect)
{
rect = gViewerWindow->getWorldViewRectRaw();
static S32 right_padding = 0;
if (right_padding == 0)
{
LLPanel* side_bar_tabs =
gViewerWindow->getRootView()->getChild<LLPanel> (
"side_bar_tabs");
right_padding = side_bar_tabs->getRect().getWidth();
LLTransientFloaterMgr::getInstance()->addControlView(side_bar_tabs);
}
rect.mRight -= right_padding;
}
void LLIMFloater::setDocked(bool docked, bool pop_on_undock)

View File

@ -429,6 +429,50 @@ LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
(LLIMModel::LLIMSession*) NULL);
}
//*TODO consider switching to using std::set instead of std::list for holding LLUUIDs across the whole code
LLIMModel::LLIMSession* LLIMModel::findAdHocIMSession(const std::vector<LLUUID>& ids)
{
S32 num = ids.size();
if (!num) return NULL;
if (mId2SessionMap.empty()) return NULL;
std::map<LLUUID, LLIMSession*>::const_iterator it = mId2SessionMap.begin();
for (; it != mId2SessionMap.end(); ++it)
{
LLIMSession* session = (*it).second;
if (!session->isAdHoc()) continue;
if (session->mInitialTargetIDs.size() != num) continue;
std::list<LLUUID> tmp_list(session->mInitialTargetIDs.begin(), session->mInitialTargetIDs.end());
std::vector<LLUUID>::const_iterator iter = ids.begin();
while (iter != ids.end())
{
tmp_list.remove(*iter);
++iter;
if (tmp_list.empty())
{
break;
}
}
if (tmp_list.empty() && iter == ids.end())
{
return session;
}
}
return NULL;
}
bool LLIMModel::LLIMSession::isAdHoc()
{
return IM_SESSION_CONFERENCE_START == mType || (IM_SESSION_INVITE == mType && !gAgent.isInGroup(mSessionID));
}
void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
LLIMSession* session = findIMSession(old_session_id);
@ -1403,11 +1447,20 @@ void LLCallDialog::getAllowedRect(LLRect& rect)
rect = gViewerWindow->getWorldViewRectScaled();
}
void LLCallDialog::onOpen(const LLSD& key)
BOOL LLCallDialog::postBuild()
{
if (!LLDockableFloater::postBuild())
return FALSE;
// dock the dialog to the Speak Button, where other sys messages appear
setDockControl(new LLDockControl(LLBottomTray::getInstance()->getChild<LLPanel>("speak_panel"),
this, getDockTongue(), LLDockControl::TOP, boost::bind(&LLCallDialog::getAllowedRect, this, _1)));
LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_panel");
setDockControl(new LLDockControl(
anchor_panel, this,
getDockTongue(), LLDockControl::TOP,
boost::bind(&LLCallDialog::getAllowedRect, this, _1)));
return TRUE;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1551,7 +1604,7 @@ void LLOutgoingCallDialog::onCancel(void* user_data)
BOOL LLOutgoingCallDialog::postBuild()
{
BOOL success = LLDockableFloater::postBuild();
BOOL success = LLCallDialog::postBuild();
childSetAction("Cancel", onCancel, this);
@ -1570,7 +1623,7 @@ LLCallDialog(payload)
BOOL LLIncomingCallDialog::postBuild()
{
LLDockableFloater::postBuild();
LLCallDialog::postBuild();
LLUUID session_id = mPayload["session_id"].asUUID();
LLSD caller_id = mPayload["caller_id"];
@ -2097,7 +2150,13 @@ BOOL LLIMMgr::getIMReceived() const
void LLIMMgr::autoStartCallOnStartup(const LLUUID& session_id)
{
LLIMModel::LLIMSession *session = LLIMModel::getInstance()->findIMSession(session_id);
if (session)
if (!session) return;
if (session->mSessionInitialized)
{
startCall(session_id);
}
else
{
session->mStartCallOnInitialize = true;
}
@ -2159,12 +2218,22 @@ LLUUID LLIMMgr::addSession(
bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
//works only for outgoing ad-hoc sessions
if (new_session && IM_SESSION_CONFERENCE_START == dialog && ids.size())
{
LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids);
if (ad_hoc_found)
{
new_session = false;
session_id = ad_hoc_found->mSessionID;
}
}
if (new_session)
{
LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids, voice);
}
//*TODO remove this "floater" thing when Communicate Floater's gone
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(!floater)

View File

@ -74,6 +74,8 @@ public:
void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
bool isAdHoc();
LLUUID mSessionID;
std::string mName;
EInstantMessage mType;
@ -133,6 +135,12 @@ public:
*/
LLIMSession* findIMSession(const LLUUID& session_id) const;
/**
* Find an Ad-Hoc IM Session with specified participants
* @return first found Ad-Hoc session or NULL if the session does not exist
*/
LLIMSession* findAdHocIMSession(const std::vector<LLUUID>& ids);
/**
* Rebind session data to a new session id.
*/
@ -476,7 +484,7 @@ public:
LLCallDialog(const LLSD& payload);
~LLCallDialog() {}
virtual void onOpen(const LLSD& key);
virtual BOOL postBuild();
protected:
virtual void getAllowedRect(LLRect& rect);

View File

@ -213,7 +213,6 @@ void LLParticipantList::updateRecentSpeakersOrder()
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
{
// Resort avatar list
mAvatarList->setDirty(true);
sort();
}
}

View File

@ -217,7 +217,10 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
ToastElem new_toast_elem(p);
// reset HIDDEN flags for the Overflow Toast
mOverflowToastHidden = false;
if(mOverflowToastPanel)
mOverflowToastPanel->setIsHidden(false);
new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1));
new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1));
@ -459,8 +462,6 @@ void LLScreenChannel::showToastsBottom()
S32 toast_margin = 0;
std::vector<ToastElem>::reverse_iterator it;
closeOverflowToastPanel();
for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
{
if(it != mToastList.rbegin())
@ -513,7 +514,11 @@ void LLScreenChannel::showToastsBottom()
mHiddenToastsNum++;
}
createOverflowToast(bottom, gSavedSettings.getS32("NotificationTipToastLifeTime"));
}
}
else
{
closeOverflowToastPanel();
}
}
//--------------------------------------------------------------------------
@ -544,11 +549,14 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
LLRect toast_rect;
LLToast::Params p;
p.lifetime_secs = timer;
mOverflowToastPanel = new LLToast(p);
if(!mOverflowToastPanel)
mOverflowToastPanel = new LLToast(p);
if(!mOverflowToastPanel)
return;
mOverflowToastPanel->startFading();
mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this));
LLTextBox* text_box = mOverflowToastPanel->getChild<LLTextBox>("toast_text");
@ -606,8 +614,8 @@ void LLScreenChannel::closeOverflowToastPanel()
{
if(mOverflowToastPanel != NULL)
{
mOverflowToastPanel->closeFloater();
mOverflowToastPanel = NULL;
mOverflowToastPanel->setVisible(FALSE);
mOverflowToastPanel->stopFading();
}
}

View File

@ -1237,6 +1237,7 @@ void LLTextureCtrl::draw()
// Using the discard level, do not show the string if the texture is almost but not
// fully loaded.
if ( mTexturep.notNull() &&
(!mTexturep->isFullyLoaded()) &&
(mShowLoadingPlaceholder == TRUE) &&
(mTexturep->getDiscardLevel() != 1) &&
(mTexturep->getDiscardLevel() != 0))

View File

@ -45,7 +45,7 @@
class LLButton;
class LLFloaterTexturePicker;
class LLInventoryItem;
class LLViewerTexture;
class LLViewerFetchedTexture;
// used for setting drag & drop callbacks.
typedef boost::function<BOOL (LLUICtrl*, LLInventoryItem*)> drag_n_drop_callback;
@ -189,7 +189,7 @@ private:
drag_n_drop_callback mDropCallback;
commit_callback_t mOnCancelCallback;
commit_callback_t mOnSelectCallback;
LLPointer<LLViewerTexture> mTexturep;
LLPointer<LLViewerFetchedTexture> mTexturep;
LLUIColor mBorderColor;
LLUUID mImageItemID;
LLUUID mImageAssetID;

View File

@ -842,10 +842,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
mLoaded = FALSE;
mGetStatus = 0;
mGetReason.clear();
lldebugs << "HTTP GET: " << mID << " Offset: " << offset
<< " Bytes: " << mRequestedSize
<< " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth
<< llendl;
LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << offset
<< " Bytes: " << mRequestedSize
<< " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << max_bandwidth
<< LL_ENDL;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
mState = WAIT_HTTP_REQ;
@ -1257,7 +1257,7 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
gTextureList.sTextureBits += data_size * 8; // Approximate - does not include header bits
//llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl;
LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL;
if (data_size > 0)
{
// *TODO: set the formatted image data here directly to avoid the copy
@ -1450,8 +1450,9 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
{
// Only do partial requests for J2C at the moment
//llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;
//llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;
desired_size = MAX_IMAGE_DATA_SIZE;
desired_discard = 0;
}
else if (desired_discard == 0)
{

View File

@ -35,13 +35,14 @@
#include "llnotifications.h"
#include "llinstantmessage.h"
#include "llviewerchat.h"
const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6;
//--------------------------------------------------------------------------
LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notification),
mAvatar(NULL), mUserName(NULL),
mTime(NULL), mMessage(NULL)
mAvatar(NULL), mUserName(NULL),
mTime(NULL), mMessage(NULL)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_instant_message.xml");
@ -52,8 +53,11 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mMessage = getChild<LLTextBox>("message");
LLStyle::Params style_params;
style_params.font.name(LLFontGL::nameFromFont(style_params.font));
style_params.font.size(LLFontGL::sizeFromFont(style_params.font));
LLFontGL* fontp = LLViewerChat::getChatFont();
std::string font_name = LLFontGL::nameFromFont(fontp);
std::string font_size = LLFontGL::sizeFromFont(fontp);
style_params.font.name(font_name);
style_params.font.size(font_size);
style_params.font.style = "UNDERLINE";
//Handle IRC styled /me messages.
@ -63,13 +67,16 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mMessage->clear();
style_params.font.style ="ITALIC";
mMessage->appendText(p.from + " ", FALSE, style_params);
mMessage->appendText(p.from, FALSE, style_params);
style_params.font.style = "ITALIC";
mMessage->appendText(p.message.substr(3), FALSE, style_params);
}
else
{
mMessage->setValue(p.message);
}
mUserName->setValue(p.from);
mTime->setValue(p.time);
mSessionID = p.session_id;

View File

@ -38,10 +38,12 @@
// Library includes
#include "llwindow.h" // spawnWebBrowser()
#include "llagent.h"
#include "llappviewer.h"
#include "llfloatermediabrowser.h"
#include "llfloaterreg.h"
#include "lllogininstance.h"
#include "llparcel.h"
#include "llsd.h"
#include "lltoastalertpanel.h"
#include "llui.h"
@ -49,6 +51,8 @@
#include "llversioninfo.h"
#include "llviewercontrol.h"
#include "llviewernetwork.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
class URLLoader : public LLToastAlertPanel::URLLoader
@ -144,7 +148,27 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
substitution["LANGUAGE"] = LLUI::getLanguage();
substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel();
substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
substitution["SESSION_ID"] = gAgent.getSessionID();
// find the region ID
LLUUID region_id;
LLViewerRegion *region = gAgent.getRegion();
if (region)
{
region_id = region->getRegionID();
}
substitution["REGION_ID"] = region_id;
// find the parcel ID
LLUUID parcel_id;
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (parcel)
{
parcel_id = parcel->getID();
}
substitution["PARCEL_ID"] = parcel_id;
// expand all of the substitution strings and escape the url
std::string expanded_url = url;
LLStringUtil::format(expanded_url, substitution);

View File

@ -334,7 +334,6 @@ void LLWorldMapView::draw()
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setColorMask(true, true);
#if 1
// Draw the image tiles
drawMipmap(width, height);
gGL.flush();
@ -452,7 +451,7 @@ void LLWorldMapView::draw()
// Draw the region name in the lower left corner
if (sMapScale >= DRAW_TEXT_THRESHOLD)
{
LLFontGL* font = LLFontGL::getFontSansSerifSmall();
LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::BOLD));
std::string mesg;
if (info->isDown())
{
@ -468,14 +467,13 @@ void LLWorldMapView::draw()
mesg, 0,
llfloor(left + 3), llfloor(bottom + 2),
LLColor4::white,
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW);
}
}
}
#endif
#if 1
// Draw background rectangle
LLGLSUIDefault gls_ui;
{
@ -566,7 +564,7 @@ void LLWorldMapView::draw()
drawTracking( LLWorldMap::getInstance()->getTrackedPositionGlobal(), loading_color, TRUE, getString("Loading"), "");
}
}
#endif
// turn off the scissor
LLGLDisable no_scissor(GL_SCISSOR_TEST);

View File

@ -2904,13 +2904,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="joined_call">Joined the voice call</string>
<string name="ringing-im">
Joining Voice Chat...
Joining voice call...
</string>
<string name="connected-im">
Connected, click End Call to hang up
</string>
<string name="hang_up-im">
Left Voice Chat
Left voice call
</string>
<string name="answering-im">
Connecting...