summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llavataractions.cpp1
-rw-r--r--indra/newview/llcallfloater.cpp191
-rw-r--r--indra/newview/llcallfloater.h93
-rw-r--r--indra/newview/llgroupactions.cpp7
-rw-r--r--indra/newview/llimfloater.cpp18
-rw-r--r--indra/newview/llimview.cpp83
-rw-r--r--indra/newview/llimview.h10
-rw-r--r--indra/newview/llparticipantlist.cpp1
-rw-r--r--indra/newview/llscreenchannel.cpp20
-rw-r--r--indra/newview/lltexturectrl.cpp1
-rw-r--r--indra/newview/lltexturectrl.h4
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
12 files changed, 355 insertions, 78 deletions
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 651c66d0a7..2a8c55e5db 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -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");
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index fe4f0c5525..c222ced98f 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -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;
-
- 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);
- }
-*/
-
- }
- }
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
- // 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
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 21fba433c6..537c57f671 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -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;
};
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 22658b4d65..7dd8ea694e 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -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");
}
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index acaa6076f8..0ce8d4b7cd 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -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)
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 8917cc11e1..3549891bc5 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -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)
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 09f0c9df71..3f46b0d754 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -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);
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 5941487c7d..7d5944ea2b 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -213,7 +213,6 @@ void LLParticipantList::updateRecentSpeakersOrder()
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
{
// Resort avatar list
- mAvatarList->setDirty(true);
sort();
}
}
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index bd256ec9c2..c18fe8ad7e 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -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();
}
}
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 5f7c2f5080..25e5e23e6f 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -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))
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 0b232da62b..fb1d591e32 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -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;
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index acdf3d1bf7..32eae9d11d 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -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...