diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 26802bbd1c1d85451ae0742a7f93f00c6c03a981..457c074ef1e6046b92c69f2a8a50198fdfb7a600 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -552,6 +552,23 @@ void LLPluginClassMedia::loadURI(const std::string &uri)
 	sendMessage(message);
 }
 
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+	const char* result = "UNKNOWN";
+	switch(priority)
+	{
+		case PRIORITY_UNLOADED:		result = "unloaded";	break;
+		case PRIORITY_STOPPED:		result = "stopped";		break;
+		case PRIORITY_HIDDEN:		result = "hidden";		break;
+		case PRIORITY_SLIDESHOW:	result = "slideshow";	break;
+		case PRIORITY_LOW:			result = "low";			break;
+		case PRIORITY_NORMAL:		result = "normal";		break;
+		case PRIORITY_HIGH:			result = "high";		break;
+	}
+	
+	return result;
+}
+
 void LLPluginClassMedia::setPriority(EPriority priority)
 {
 	if(mPriority != priority)
@@ -560,35 +577,28 @@ void LLPluginClassMedia::setPriority(EPriority priority)
 
 		LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
 		
-		std::string priority_string;
+		std::string priority_string = priorityToString(priority);
 		switch(priority)
 		{
 			case PRIORITY_UNLOADED:	
-				priority_string = "unloaded";	
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_STOPPED:	
-				priority_string = "stopped";	
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_HIDDEN:	
-				priority_string = "hidden";	
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_SLIDESHOW:
-				priority_string = "slideshow";		
 				mSleepTime = 1.0f;
 			break;
 			case PRIORITY_LOW:		
-				priority_string = "low";		
 				mSleepTime = 1.0f / 50.0f;
 			break;
 			case PRIORITY_NORMAL:	
-				priority_string = "normal";	
 				mSleepTime = 1.0f / 100.0f;
 			break;
 			case PRIORITY_HIGH:		
-				priority_string = "high";		
 				mSleepTime = 1.0f / 100.0f;
 			break;
 		}
@@ -794,6 +804,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
 			{
 				mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
 			}
+			else if(status == "done")
+			{
+				mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+			}
 			else
 			{
 				// empty string or any unknown string
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 4f9763474e14b3f2fa00e2bca1900e80c49a07e6..90ecd1e0735d3792699f7a332ae4264dc8bf2b7d 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -150,6 +150,7 @@ class LLPluginClassMedia : public LLPluginProcessParentOwner
 		PRIORITY_HIGH		// media has user focus and/or is taking up most of the screen
 	}EPriority;
 
+	static const char* priorityToString(EPriority priority);
 	void setPriority(EPriority priority);
 	void setLowPrioritySizeLimit(int size);
 	
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index 4690f09172489523b357d9aea55db60294e393c1..c798af29caf1e1c3e9a742f21f70ff1060bbf1ec 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -70,7 +70,8 @@ class LLPluginClassMediaOwner
 		MEDIA_ERROR,		// navigation/preroll failed
 		MEDIA_PLAYING,		// playing (only for time-based media)
 		MEDIA_PAUSED,		// paused (only for time-based media)
-		
+		MEDIA_DONE			// finished playing (only for time-based media)
+	
 	} EMediaStatus;
 	
 	virtual ~LLPluginClassMediaOwner() {};
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index e053477d58e1acd19074713634a07b5aa117de89..75905d092740d4e838eb12e53a83b00e7d5f9f6f 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1544,18 +1544,24 @@ void LLLineEditor::drawBackground()
 		image = mBgImage;
 	}
 	
+	F32 alpha = getDrawContext().mAlpha;
 	// optionally draw programmatic border
 	if (has_focus)
 	{
+		LLColor4 tmp_color = gFocusMgr.getFocusColor();
+		tmp_color.setAlpha(alpha);
 		image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(),
-						  gFocusMgr.getFocusColor(),
+						  tmp_color,
 						  gFocusMgr.getFocusFlashWidth());
 	}
-	image->draw(getLocalRect());
+	LLColor4 tmp_color = UI_VERTEX_COLOR;
+	tmp_color.setAlpha(alpha);
+	image->draw(getLocalRect(), tmp_color);
 }
 
 void LLLineEditor::draw()
 {
+	F32 alpha = getDrawContext().mAlpha;
 	S32 text_len = mText.length();
 	static LLUICachedControl<S32> lineeditor_cursor_thickness ("UILineEditorCursorThickness", 0);
 	static LLUICachedControl<S32> lineeditor_v_pad ("UILineEditorVPad", 0);
@@ -1608,8 +1614,10 @@ void LLLineEditor::draw()
 	{
 		text_color = mReadOnlyFgColor.get();
 	}
+	text_color.setAlpha(alpha);
 	LLColor4 label_color = mTentativeFgColor.get();
-
+	label_color.setAlpha(alpha);
+	
 	if (hasPreeditString())
 	{
 		// Draw preedit markers.  This needs to be before drawing letters.
@@ -1632,7 +1640,7 @@ void LLLineEditor::draw()
 						preedit_pixels_right - preedit_standout_gap - 1,
 						background.mBottom + preedit_standout_position - preedit_standout_thickness,
 						(text_color * preedit_standout_brightness 
-						 + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(1.0f));
+						 + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/));
 				}
 				else
 				{
@@ -1641,7 +1649,7 @@ void LLLineEditor::draw()
 						preedit_pixels_right - preedit_marker_gap - 1,
 						background.mBottom + preedit_marker_position - preedit_marker_thickness,
 						(text_color * preedit_marker_brightness
-						 + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(1.0f));
+						 + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/));
 				}
 			}
 		}
@@ -1684,15 +1692,17 @@ void LLLineEditor::draw()
 		if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
 		{
 			LLColor4 color = mHighlightColor;
+			color.setAlpha(alpha);
 			// selected middle
 			S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
 			width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
 			gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
 
+			LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
 			rendered_text += mGLFont->render( 
 				mText, mScrollHPos + rendered_text,
 				rendered_pixels_right, text_bottom,
-				LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+				tmp_color,
 				LLFontGL::LEFT, LLFontGL::BOTTOM,
 				0,
 				LLFontGL::NO_SHADOW,
@@ -1758,8 +1768,9 @@ void LLLineEditor::draw()
 					cursor_right, cursor_bottom, text_color);
 				if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
 				{
+					LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
 					mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom, 
-						LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+						tmp_color,
 						LLFontGL::LEFT, LLFontGL::BOTTOM,
 						0,
 						LLFontGL::NO_SHADOW,
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 732c01614bc35798b752d2dba2ca8b3d502e7b30..cde4c755184d899c97053e8c069235f0a17c25ad 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -44,6 +44,7 @@
 #include "lluictrlfactory.h"
 #include "llrender.h"
 #include "llfloater.h"
+#include "lltrans.h"
 
 //----------------------------------------------------------------------------
 
@@ -153,6 +154,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
 	mRightTabBtnOffset(p.tab_padding_right),
 	mTotalTabWidth(0),
 	mTabPosition(p.tab_position),
+	mFontHalign(p.font_halign),
+	mFont(p.font.isProvided() ? p.font() : (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall())),
 	mFirstTabParams(p.first_tab),
 	mMiddleTabParams(p.middle_tab),
 	mLastTabParams(p.last_tab)
@@ -401,12 +404,6 @@ void LLTabContainer::draw()
 					}
 				}
 			}
-			LLUI::pushMatrix();
-			{
-				LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
-				tuple->mButton->draw();
-			}
-			LLUI::popMatrix();
 
 			idx++;
 		}
@@ -641,12 +638,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
 				}
 			}
 		}
-
-		for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
-		{
-			LLTabTuple* tuple = *iter;
-			tuple->mButton->setVisible( FALSE );
-		}
 	}
 	return handled;
 }
@@ -836,8 +827,6 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 		// already a child of mine
 		return;
 	}
-	const LLFontGL* font =
-		(mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall());
 
 	// Store the original label for possible xml export.
 	child->setLabel(label);
@@ -847,7 +836,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 	S32 button_width = mMinTabWidth;
 	if (!mIsVertical)
 	{
-		button_width = llclamp(font->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
+		button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
 	}
 	
 	// Tab panel
@@ -934,7 +923,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 		params.name(trimmed_label);
 		params.rect(btn_rect);
 		params.initial_value(trimmed_label);
-		params.font(font);
+		params.font(mFont);
 		textbox = LLUICtrlFactory::create<LLTextBox> (params);
 		
 		LLButton::Params p;
@@ -950,12 +939,12 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 			p.rect(btn_rect);
 			p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
 			p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
-			p.font(font);
+			p.font(mFont);
 			p.label(trimmed_label);
 			p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
 			p.image_selected(mMiddleTabParams.tab_left_image_selected);
 			p.scale_image(true);
-			p.font_halign = LLFontGL::LEFT;
+			p.font_halign = mFontHalign;
 			p.tab_stop(false);
 			if (indent)
 			{
@@ -965,18 +954,13 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 		}
 		else
 		{
-			std::string tooltip = trimmed_label;
-			tooltip += "\nAlt-Left arrow for previous tab";
-			tooltip += "\nAlt-Right arrow for next tab";
-
 			LLButton::Params p;
 			p.name(std::string(child->getName()) + " tab");
 			p.rect(btn_rect);
 			p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
-			p.font(font);
+			p.font(mFont);
 			p.label(trimmed_label);
 			p.visible(false);
-			p.tool_tip(tooltip);
 			p.scale_image(true);
 			p.image_unselected(tab_img);
 			p.image_selected(tab_selected_img);
@@ -984,7 +968,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
 			// Try to squeeze in a bit more text
 			p.pad_left(4);
 			p.pad_right(2);
-			p.font_halign = LLFontGL::LEFT;
+			p.font_halign = mFontHalign;
 			p.follows.flags = FOLLOWS_LEFT;
 			p.follows.flags = FOLLOWS_LEFT;
 	
@@ -1505,7 +1489,6 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
 
 		if (!mIsVertical)
 		{
-			const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
 			// remove current width from total tab strip width
 			mTotalTabWidth -= tuple->mButton->getRect().getWidth();
 
@@ -1516,7 +1499,7 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
 			tuple->mPadding = image_overlay_width;
 
 			tuple->mButton->setRightHPad(6);
-			tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), 
+			tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), 
 									tuple->mButton->getRect().getHeight());
 			// add back in button width to total tab strip width
 			mTotalTabWidth += tuple->mButton->getRect().getWidth();
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index a81974cd4226b826cbf8094d5875793c67280860..be9c6c7d065849cc0803ec3d4951b97bea2f1b7f 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -262,6 +262,9 @@ class LLTabContainer : public LLPanel
 	S32								mTabHeight;
 
 	LLFrameTimer					mDragAndDropDelayTimer;
+	
+	LLFontGL::HAlign                mFontHalign;
+	const LLFontGL*					mFont;
 
 	TabParams						mFirstTabParams;
 	TabParams						mMiddleTabParams;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 0add3fb500a00043c945e674f0a33ba717ef6e51..2b1d677ffb7ffaec05b39d2305fcb26ec87f3556 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -419,9 +419,6 @@ void LLTextBase::drawCursor()
 			return;
 		}
 
-		if (!mTextRect.contains(cursor_rect))
-			return;
-
 		// Draw the cursor
 		// (Flash the cursor every half second starting a fixed time after the last keystroke)
 		F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
@@ -973,7 +970,7 @@ void LLTextBase::draw()
 							: hasFocus() 
 								? mFocusBgColor.get() 
 								: mWriteableBgColor.get();
-		gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE);
+		gl_rect_2d(mTextRect, bg_color, TRUE);
 	}
 
 	// draw document view
@@ -1034,13 +1031,13 @@ S32 LLTextBase::getLeftOffset(S32 width)
 	switch (mHAlign)
 	{
 	case LLFontGL::LEFT:
-		return 0;
+		return mHPad;
 	case LLFontGL::HCENTER:
-		return (mTextRect.getWidth() - width) / 2;
+		return mHPad + (mTextRect.getWidth() - width - mHPad) / 2;
 	case LLFontGL::RIGHT:
 		return mTextRect.getWidth() - width;
 	default:
-		return 0;
+		return mHPad;
 	}
 }
 
@@ -1048,8 +1045,6 @@ S32 LLTextBase::getLeftOffset(S32 width)
 static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
 void LLTextBase::reflow(S32 start_index)
 {
-	if (!mReflowNeeded) return;
-
 	LLFastTimer ft(FTM_TEXT_REFLOW);
 
 	updateSegments();
@@ -1078,7 +1073,7 @@ void LLTextBase::reflow(S32 start_index)
 		segment_set_t::iterator seg_iter = mSegments.begin();
 		S32 seg_offset = 0;
 		S32 line_start_index = 0;
-		const S32 text_width = mTextRect.getWidth();  // optionally reserve room for margin
+		const S32 text_width = mTextRect.getWidth() - mHPad;  // reserve room for margin
 		S32 remaining_pixels = text_width;
 		LLWString text(getWText());
 		S32 line_count = 0;
@@ -2037,7 +2032,6 @@ void LLTextBase::updateRects()
 	}
 	else
 	{
-
 		mContentsRect = mLineInfoList.begin()->mRect;
 		for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
 			line_iter != mLineInfoList.end();
@@ -2046,13 +2040,28 @@ void LLTextBase::updateRects()
 			mContentsRect.unionWith(line_iter->mRect);
 		}
 
-		mContentsRect.mRight += mHPad;
+		mContentsRect.mLeft = 0;
 		mContentsRect.mTop += mVPad;
-		// get around rounding errors when clipping text against rectangle
-		mContentsRect.stretch(1);
+
+		S32 delta_pos = -mContentsRect.mBottom;
+		// move line segments to fit new document rect
+		for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
+		{
+			it->mRect.translate(0, delta_pos);
+		}
+		mContentsRect.translate(0, delta_pos);
 	}
 
+	// update document container dimensions according to text contents
+	LLRect doc_rect = mContentsRect;
+	// use old mTextRect constraint document to width of viewable region
+	doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+
+	mDocumentView->setShape(doc_rect);
 
+	//update mTextRect *after* mDocumentView has been resized
+	// so that scrollbars are added if document needs to scroll
+	// since mTextRect does not include scrollbars
 	LLRect old_text_rect = mTextRect;
 	mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
 	//FIXME: replace border with image?
@@ -2060,43 +2069,14 @@ void LLTextBase::updateRects()
 	{
 		mTextRect.stretch(-1);
 	}
-	mTextRect.mLeft += mHPad;
-	mTextRect.mTop -= mVPad;
 	if (mTextRect != old_text_rect)
 	{
 		needsReflow();
 	}
 
-	// change document rect size too
-	LLRect document_rect;
-	if (mScroller)
-	{
-		// document is size of scroller or size of text contents, whichever is larger
-		document_rect.setOriginAndSize(0, 0, 
-									mScroller->getContentWindowRect().getWidth(), 
-									llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
-	}
-	else
-	{
-		// document size is just extents of reflowed text, reset to origin 0,0
-		document_rect.set(0, 
-						getLocalRect().getHeight(), 
-						getLocalRect().getWidth(), 
-						llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight()));
-	}
-	mDocumentView->setShape(document_rect);
-
-	// after making document big enough to hold all the text, move the text to fit in the document
-	if (!mLineInfoList.empty())
-	{
-		S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
-		// move line segments to fit new document rect
-		for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
-		{
-			it->mRect.translate(0, delta_pos);
-		}
-		mContentsRect.translate(0, delta_pos);
-	}
+	// update document container again, using new mTextRect
+	doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+	mDocumentView->setShape(doc_rect);
 }
 
 
@@ -2398,7 +2378,6 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 	{
 		if (text[last_char] == '\n') 
 		{
-			last_char++;
 			break;
 		}
 	}
@@ -2418,9 +2397,14 @@ S32	LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 		// If at the beginning of a line, and a single character won't fit, draw it anyway
 		num_chars = 1;
 	}
-	if (mStart + segment_offset + num_chars == mEditor.getLength())
+
+	// include *either* the EOF or newline character in this run of text
+	// but not both
+	S32 last_char_in_run = mStart + segment_offset + num_chars;
+	// check length first to avoid indexing off end of string
+	if (last_char_in_run >= mEditor.getLength() 
+		|| text[last_char_in_run] == '\n')
 	{
-		// include terminating NULL
 		num_chars++;
 	}
 	return num_chars;
@@ -2442,12 +2426,14 @@ void LLNormalTextSegment::dump() const
 // LLInlineViewSegment
 //
 
-LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line, S32 hpad, S32 vpad)
+LLInlineViewSegment::LLInlineViewSegment(const Params& p, S32 start, S32 end)
 :	LLTextSegment(start, end),
-	mView(view),
-	mForceNewLine(force_new_line),
-	mHPad(hpad), // one sided padding (applied to left and right)
-	mVPad(vpad)
+	mView(p.view),
+	mForceNewLine(p.force_newline),
+	mLeftPad(p.left_pad),
+	mRightPad(p.right_pad),
+	mTopPad(p.top_pad),
+	mBottomPad(p.bottom_pad)
 {
 } 
 
@@ -2467,8 +2453,8 @@ void	LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
 	}
 	else
 	{
-		width = mHPad * 2 + mView->getRect().getWidth();
-		height = mVPad * 2 + mView->getRect().getHeight();
+		width = mLeftPad + mRightPad + mView->getRect().getWidth();
+		height = mBottomPad + mTopPad + mView->getRect().getHeight();
 	}
 }
 
@@ -2491,14 +2477,14 @@ S32	LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
 void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
 {
 	LLRect start_rect = editor.getDocRectFromDocIndex(mStart);
-	mView->setOrigin(start_rect.mLeft + mHPad, start_rect.mBottom + mVPad);
+	mView->setOrigin(start_rect.mLeft + mLeftPad, start_rect.mBottom + mBottomPad);
 }
 
 F32	LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
 {
 	// return padded width of widget
 	// widget is actually drawn during mDocumentView's draw()
-	return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mHPad * 2);
+	return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mLeftPad + mRightPad);
 }
 
 void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index d0787f001ebbaf66b2797abb2e7bc3994624c65e..14fd786127115792b6c64b082d9795ca5d27c1d3 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -459,7 +459,17 @@ class LLIndexSegment : public LLTextSegment
 class LLInlineViewSegment : public LLTextSegment
 {
 public:
-	LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line, S32 hpad = 0, S32 vpad = 0);
+	struct Params : public LLInitParam::Block<Params>
+	{
+		Mandatory<LLView*>		view;
+		Optional<bool>			force_newline;
+		Optional<S32>			left_pad,
+								right_pad,
+								bottom_pad,
+								top_pad;
+	};
+
+	LLInlineViewSegment(const Params& p, S32 start, S32 end);
 	~LLInlineViewSegment();
 	/*virtual*/ void		getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
 	/*virtual*/ S32			getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
@@ -470,8 +480,10 @@ class LLInlineViewSegment : public LLTextSegment
 	/*virtual*/ void		linkToDocument(class LLTextBase* editor);
 
 private:
-	S32 mHPad;
-	S32 mVPad;
+	S32 mLeftPad;
+	S32 mRightPad;
+	S32 mTopPad;
+	S32 mBottomPad;
 	LLView* mView;
 	bool	mForceNewLine;
 };
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 570ca4b998ce91cf8b17f19237652736c24dfc6b..f0238dba4927df5be507d2011a1224c358b1f985 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2307,7 +2307,7 @@ void LLTextEditor::insertText(const std::string &new_text)
 	setEnabled( enabled );
 }
 
-void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line, S32 hpad, S32 vpad)
+void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
 {
 	// Save old state
 	S32 selection_start = mSelectionStart;
@@ -2321,12 +2321,9 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
 
 	setCursorPos(old_length);
 
-	LLWString widget_wide_text;
+	LLWString widget_wide_text = utf8str_to_wstring(text);
 
-	// Add carriage return if not first line
-	widget_wide_text = utf8str_to_wstring(widget_text);
-
-	LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line, hpad, vpad);
+	LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
 	insert(getLength(), widget_wide_text, FALSE, segment);
 
 	needsReflow();
@@ -2349,7 +2346,7 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
 		setCursorPos(cursor_pos);
 	}
 
-	if( !allow_undo )
+	if (!allow_undo)
 	{
 		blockUndo();
 	}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 4847f4d117abc8a2e731750122426a0694988e72..10fc94dedc1e4810785ec474947932efd72df17a 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -166,7 +166,7 @@ class LLTextEditor :
 	// inserts text at cursor
 	void			insertText(const std::string &text);
 
-	void			appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline, S32 hpad, S32 vpad);
+	void			appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
 	// Non-undoable
 	void			setText(const LLStringExplicit &utf8str);
 
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
index 0b7092fad601ecf94e5d97a7bdb15c5af1360457..6acac074233cb578171a71a4c07b90535fde6449 100644
--- a/indra/media_plugins/base/media_plugin_base.cpp
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -64,6 +64,7 @@ std::string MediaPluginBase::statusString()
 		case STATUS_ERROR:		result = "error";		break;
 		case STATUS_PLAYING:	result = "playing";		break;
 		case STATUS_PAUSED:		result = "paused";		break;
+		case STATUS_DONE:		result = "done";		break;
 		default:
 			// keep the empty string
 		break;
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
index 8f600cb8d617385845627a6117deb1eb139a1f13..f1e96335f92e301170369343ca64292dcaee840f 100644
--- a/indra/media_plugins/base/media_plugin_base.h
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -56,6 +56,7 @@ class MediaPluginBase
 		STATUS_ERROR,
 		STATUS_PLAYING,
 		STATUS_PAUSED,
+		STATUS_DONE
 	} EStatus;
 
 	class SharedSegmentInfo
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index c9ee1c8ac777028c228a8a8d65afe511028a3f05..fb6d5b29054ce58dd61177322d236c9add308e69 100644
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -420,7 +420,7 @@ class MediaPluginQuickTime : public MediaPluginBase
 	{
 		if ( mCommand == COMMAND_PLAY )
 		{
-			if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING )
+			if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
 			{
 				long state = GetMovieLoadState( mMovieHandle );
 
@@ -446,7 +446,7 @@ class MediaPluginQuickTime : public MediaPluginBase
 		else
 		if ( mCommand == COMMAND_STOP )
 		{
-			if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED )
+			if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
 			{
 				if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
 				{
@@ -547,12 +547,12 @@ class MediaPluginQuickTime : public MediaPluginBase
 
 		// see if title arrived and if so, update member variable with contents
 		checkTitle();
-
-		// special code for looping - need to rewind at the end of the movie
-		if ( mIsLooping )
+		
+		// QT call to see if we are at the end - can't do with controller
+		if ( IsMovieDone( mMovieHandle ) )
 		{
-			// QT call to see if we are at the end - can't do with controller
-			if ( IsMovieDone( mMovieHandle ) )
+			// special code for looping - need to rewind at the end of the movie
+			if ( mIsLooping )
 			{
 				// go back to start
 				rewind();
@@ -565,8 +565,16 @@ class MediaPluginQuickTime : public MediaPluginBase
 					// set the volume
 					MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
 				};
-			};
-		};
+			}
+			else
+			{
+				if(mStatus == STATUS_PLAYING)
+				{
+					setStatus(STATUS_DONE);
+				}
+			}
+		}
+
 	};
 
 	int getDataWidth() const
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index dd3937a6eff2e79a81bb13bfb919a682919b3567..a7681e4a1d047bfb72bf3e057c6153fc550cd689 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -63,13 +63,13 @@ include_directories(
     )
 
 set(viewer_SOURCE_FILES
-    llaccordionctrltab.cpp
     llaccordionctrl.cpp
+    llaccordionctrltab.cpp
     llagent.cpp
-    llagentlistener.cpp
     llagentaccess.cpp
     llagentdata.cpp
     llagentlanguage.cpp
+    llagentlistener.cpp
     llagentpicksinfo.cpp
     llagentpilot.cpp
     llagentui.cpp
@@ -78,8 +78,8 @@ set(viewer_SOURCE_FILES
     llappearancemgr.cpp
     llappviewer.cpp
     llappviewerlistener.cpp
-    llassetuploadresponders.cpp
     llassetuploadqueue.cpp
+    llassetuploadresponders.cpp
     llaudiosourcevo.cpp
     llavataractions.cpp
     llavatariconctrl.cpp
@@ -95,8 +95,8 @@ set(viewer_SOURCE_FILES
     llcaphttpsender.cpp
     llchannelmanager.cpp
     llchatbar.cpp
-    llchatitemscontainerctrl.cpp
     llchathistory.cpp
+    llchatitemscontainerctrl.cpp
     llchatmsgbox.cpp
     llchiclet.cpp
     llclassifiedinfo.cpp
@@ -116,10 +116,10 @@ set(viewer_SOURCE_FILES
     lldirpicker.cpp
     lldndbutton.cpp
     lldrawable.cpp
+    lldrawpool.cpp
     lldrawpoolalpha.cpp
     lldrawpoolavatar.cpp
     lldrawpoolbump.cpp
-    lldrawpool.cpp
     lldrawpoolground.cpp
     lldrawpoolsimple.cpp
     lldrawpoolsky.cpp
@@ -151,8 +151,8 @@ set(viewer_SOURCE_FILES
     llfloaterbuildoptions.cpp
     llfloaterbulkpermission.cpp
     llfloaterbump.cpp
-    llfloaterbuycontents.cpp
     llfloaterbuy.cpp
+    llfloaterbuycontents.cpp
     llfloaterbuycurrency.cpp
     llfloaterbuyland.cpp
     llfloatercall.cpp
@@ -163,8 +163,8 @@ set(viewer_SOURCE_FILES
     llfloatercustomize.cpp
     llfloaterdaycycle.cpp
     llfloaterenvsettings.cpp
-    llfloaterfriends.cpp
     llfloaterfonttest.cpp
+    llfloaterfriends.cpp
     llfloatergesture.cpp
     llfloatergodtools.cpp
     llfloatergroupinvite.cpp
@@ -172,8 +172,6 @@ set(viewer_SOURCE_FILES
     llfloaterhandler.cpp
     llfloaterhardwaresettings.cpp
     llfloaterhelpbrowser.cpp
-    llfloatermediabrowser.cpp
-    llfloatermediasettings.cpp
     llfloaterhud.cpp
     llfloaterimagepreview.cpp
     llfloaterinspect.cpp
@@ -183,6 +181,8 @@ set(viewer_SOURCE_FILES
     llfloaterland.cpp
     llfloaterlandholdings.cpp
     llfloatermap.cpp
+    llfloatermediabrowser.cpp
+    llfloatermediasettings.cpp
     llfloatermemleak.cpp
     llfloaternamedesc.cpp
     llfloaternotificationsconsole.cpp
@@ -227,8 +227,8 @@ set(viewer_SOURCE_FILES
     llgroupmgr.cpp
     llgroupnotify.cpp
     llhomelocationresponder.cpp
-    llhudeffectbeam.cpp
     llhudeffect.cpp
+    llhudeffectbeam.cpp
     llhudeffectlookat.cpp
     llhudeffectpointat.cpp
     llhudeffecttrail.cpp
@@ -238,11 +238,11 @@ set(viewer_SOURCE_FILES
     llhudrender.cpp
     llhudtext.cpp
     llhudview.cpp
+    llimcontrolpanel.cpp
     llimfloater.cpp
     llimhandler.cpp
     llimpanel.cpp
     llimview.cpp
-    llimcontrolpanel.cpp
     llinspect.cpp
     llinspectavatar.cpp
     llinspectgroup.cpp
@@ -260,7 +260,6 @@ set(viewer_SOURCE_FILES
     lllocaltextureobject.cpp
     lllocationhistory.cpp
     lllocationinputctrl.cpp
-    llurllineeditorctrl.cpp
     lllogchat.cpp
     llloginhandler.cpp
     lllogininstance.cpp
@@ -312,8 +311,8 @@ set(viewer_SOURCE_FILES
     llpanelgrouplandmoney.cpp
     llpanelgroupnotices.cpp
     llpanelgrouproles.cpp
-    llpanelinventory.cpp
     llpanelimcontrolpanel.cpp
+    llpanelinventory.cpp
     llpanelland.cpp
     llpanellandaudio.cpp
     llpanellandmarks.cpp
@@ -322,11 +321,10 @@ set(viewer_SOURCE_FILES
     llpanellookinfo.cpp
     llpanellooks.cpp
     llpanelmedia.cpp
-    llpanelmediahud.cpp
-    llpanelmeprofile.cpp
     llpanelmediasettingsgeneral.cpp
-    llpanelmediasettingssecurity.cpp
     llpanelmediasettingspermissions.cpp
+    llpanelmediasettingssecurity.cpp
+    llpanelmeprofile.cpp
     llpanelobject.cpp
     llpanelpeople.cpp
     llpanelpeoplemenus.cpp
@@ -335,11 +333,12 @@ set(viewer_SOURCE_FILES
     llpanelpicks.cpp
     llpanelplace.cpp
     llpanelplaceinfo.cpp
-    llpanelshower.cpp
     llpanelplaces.cpp
     llpanelplacestab.cpp
+    llpanelprimmediacontrols.cpp
     llpanelprofile.cpp
     llpanelprofileview.cpp
+    llpanelshower.cpp
     llpanelteleporthistory.cpp
     llpanelvolume.cpp
     llparcelselection.cpp
@@ -348,8 +347,8 @@ set(viewer_SOURCE_FILES
     llplacesinventorybridge.cpp
     llpolymesh.cpp
     llpolymorph.cpp
-    llpreviewanim.cpp
     llpreview.cpp
+    llpreviewanim.cpp
     llpreviewgesture.cpp
     llpreviewnotecard.cpp
     llpreviewscript.cpp
@@ -371,6 +370,7 @@ set(viewer_SOURCE_FILES
     llsky.cpp
     llslurl.cpp
     llspatialpartition.cpp
+    llspeakers.cpp
     llsplitbutton.cpp
     llsprite.cpp
     llstartup.cpp
@@ -397,10 +397,10 @@ set(viewer_SOURCE_FILES
     lltoastimpanel.cpp
     lltoastnotifypanel.cpp
     lltoastpanel.cpp
+    lltool.cpp
     lltoolbar.cpp
     lltoolbrush.cpp
     lltoolcomp.cpp
-    lltool.cpp
     lltooldraganddrop.cpp
     lltoolface.cpp
     lltoolfocus.cpp
@@ -424,6 +424,7 @@ set(viewer_SOURCE_FILES
     llurl.cpp
     llurldispatcher.cpp
     llurlhistory.cpp
+    llurllineeditorctrl.cpp
     llurlsimstring.cpp
     llurlwhitelist.cpp
     llvectorperfoptions.cpp
@@ -440,18 +441,18 @@ set(viewer_SOURCE_FILES
     llviewerhelp.cpp
     llviewerhelputil.cpp
     llviewerinventory.cpp
-    llviewerjointattachment.cpp
     llviewerjoint.cpp
+    llviewerjointattachment.cpp
     llviewerjointmesh.cpp
-    llviewerjointmesh_sse2.cpp
     llviewerjointmesh_sse.cpp
+    llviewerjointmesh_sse2.cpp
     llviewerjointmesh_vec.cpp
     llviewerjoystick.cpp
     llviewerkeyboard.cpp
     llviewerlayer.cpp
     llviewermedia.cpp
-    llviewermediafocus.cpp
     llviewermedia_streamingaudio.cpp
+    llviewermediafocus.cpp
     llviewermenu.cpp
     llviewermenufile.cpp
     llviewermessage.cpp
@@ -484,10 +485,11 @@ set(viewer_SOURCE_FILES
     llvoclouds.cpp
     llvograss.cpp
     llvoground.cpp
+    llvoicechannel.cpp
     llvoiceclient.cpp
+    llvoicecontrolpanel.cpp
     llvoiceremotectrl.cpp
     llvoicevisualizer.cpp
-    llvoicecontrolpanel.cpp
     llvoinventorylistener.cpp
     llvopartgroup.cpp
     llvosky.cpp
@@ -538,25 +540,25 @@ endif (LINUX)
 set(viewer_HEADER_FILES
     CMakeLists.txt
     ViewerInstall.cmake
-    llaccordionctrltab.h
     llaccordionctrl.h
+    llaccordionctrltab.h
     llagent.h
-    llagentlistener.h
     llagentaccess.h
     llagentdata.h
     llagentlanguage.h
+    llagentlistener.h
     llagentpicksinfo.h
     llagentpilot.h
     llagentui.h
     llagentwearables.h
     llanimstatelabels.h
     llappearance.h
+    llappearancemgr.h
     llappviewer.h
     llappviewerlistener.h
-    llassetuploadresponders.h
     llassetuploadqueue.h
+    llassetuploadresponders.h
     llaudiosourcevo.h
-    llappearancemgr.h
     llavataractions.h
     llavatariconctrl.h
     llavatarlist.h
@@ -572,8 +574,8 @@ set(viewer_HEADER_FILES
     llcaphttpsender.h
     llchannelmanager.h
     llchatbar.h
-    llchatitemscontainerctrl.h
     llchathistory.h
+    llchatitemscontainerctrl.h
     llchatmsgbox.h
     llchiclet.h
     llclassifiedinfo.h
@@ -650,8 +652,6 @@ set(viewer_HEADER_FILES
     llfloaterhandler.h
     llfloaterhardwaresettings.h
     llfloaterhelpbrowser.h
-    llfloatermediabrowser.h
-    llfloatermediasettings.h
     llfloaterhud.h
     llfloaterimagepreview.h
     llfloaterinspect.h
@@ -661,16 +661,18 @@ set(viewer_HEADER_FILES
     llfloaterland.h
     llfloaterlandholdings.h
     llfloatermap.h
+    llfloatermediabrowser.h
+    llfloatermediasettings.h
     llfloatermemleak.h
     llfloaternamedesc.h
     llfloaternotificationsconsole.h
     llfloateropenobject.h
     llfloaterparcel.h
     llfloaterpay.h
+    llfloaterperms.h
     llfloaterpostcard.h
     llfloaterpostprocess.h
     llfloaterpreference.h
-    llfloaterperms.h
     llfloaterproperties.h
     llfloaterregioninfo.h
     llfloaterreporter.h
@@ -716,12 +718,12 @@ set(viewer_HEADER_FILES
     llhudrender.h
     llhudtext.h
     llhudview.h
+    llimcontrolpanel.h
     llimfloater.h
     llimpanel.h
     llimview.h
-    llimcontrolpanel.h
-    llinspectavatar.h
     llinspect.h
+    llinspectavatar.h
     llinspectgroup.h
     llinspectobject.h
     llinventorybridge.h
@@ -738,7 +740,6 @@ set(viewer_HEADER_FILES
     lllocaltextureobject.h
     lllocationhistory.h
     lllocationinputctrl.h
-    llurllineeditorctrl.h
     lllogchat.h
     llloginhandler.h
     lllogininstance.h
@@ -747,6 +748,7 @@ set(viewer_HEADER_FILES
     llmanipscale.h
     llmaniptranslate.h
     llmapresponders.h
+    llmediactrl.h
     llmediadataclient.h
     llmediaremotectrl.h
     llmemoryview.h
@@ -786,8 +788,8 @@ set(viewer_HEADER_FILES
     llpanelgrouplandmoney.h
     llpanelgroupnotices.h
     llpanelgrouproles.h
-    llpanelinventory.h
     llpanelimcontrolpanel.h
+    llpanelinventory.h
     llpanelland.h
     llpanellandaudio.h
     llpanellandmarks.h
@@ -796,11 +798,10 @@ set(viewer_HEADER_FILES
     llpanellookinfo.h
     llpanellooks.h
     llpanelmedia.h
-    llpanelmediahud.h
-    llpanelmeprofile.h
     llpanelmediasettingsgeneral.h
-    llpanelmediasettingssecurity.h
     llpanelmediasettingspermissions.h
+    llpanelmediasettingssecurity.h
+    llpanelmeprofile.h
     llpanelobject.h
     llpanelpeople.h
     llpanelpeoplemenus.h
@@ -809,11 +810,12 @@ set(viewer_HEADER_FILES
     llpanelpicks.h
     llpanelplace.h
     llpanelplaceinfo.h
-    llpanelshower.h
     llpanelplaces.h
     llpanelplacestab.h
+    llpanelprimmediacontrols.h
     llpanelprofile.h
     llpanelprofileview.h
+    llpanelshower.h
     llpanelteleporthistory.h
     llpanelvolume.h
     llparcelselection.h
@@ -836,9 +838,9 @@ set(viewer_HEADER_FILES
     llremoteparcelrequest.h
     llresourcedata.h
     llrootview.h
+    llsavedsettingsglue.h
     llscreenchannel.h
     llscrollingpanelparam.h
-    llsavedsettingsglue.h
     llsearchcombobox.h
     llsearchhistory.h
     llselectmgr.h
@@ -847,6 +849,7 @@ set(viewer_HEADER_FILES
     llsky.h
     llslurl.h
     llspatialpartition.h
+    llspeakers.h
     llsplitbutton.h
     llsprite.h
     llstartup.h
@@ -902,6 +905,7 @@ set(viewer_HEADER_FILES
     llurl.h
     llurldispatcher.h
     llurlhistory.h
+    llurllineeditorctrl.h
     llurlsimstring.h
     llurlwhitelist.h
     llvectorperfoptions.h
@@ -925,8 +929,8 @@ set(viewer_HEADER_FILES
     llviewerkeyboard.h
     llviewerlayer.h
     llviewermedia.h
-    llviewermediaobserver.h
     llviewermediafocus.h
+    llviewermediaobserver.h
     llviewermenu.h
     llviewermenufile.h
     llviewermessage.h
@@ -960,10 +964,11 @@ set(viewer_HEADER_FILES
     llvoclouds.h
     llvograss.h
     llvoground.h
+    llvoicechannel.h
     llvoiceclient.h
+    llvoicecontrolpanel.h
     llvoiceremotectrl.h
     llvoicevisualizer.h
-    llvoicecontrolpanel.h
     llvoinventorylistener.h
     llvopartgroup.h
     llvosky.h
@@ -981,7 +986,6 @@ set(viewer_HEADER_FILES
     llwearabledictionary.h
     llwearablelist.h
     llweb.h
-    llmediactrl.h
     llwind.h
     llwindebug.h
     llwlanimator.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 63a4435408df2312518efba1c18ff4c10a9e39d2..568e8deb59056e2ac6b9f3a2eee9b4ace60973be 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7753,6 +7753,39 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>FriendsListShowIcons</key>
+    <map>
+      <key>Comment</key>
+      <string>Show/hide online and all friends icons in the friend list</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>NearbyListShowIcons</key>
+    <map>
+      <key>Comment</key>
+      <string>Show/hide people icons in nearby list</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>RecentListShowIcons</key>
+    <map>
+      <key>Comment</key>
+      <string>Show/hide people icons in recent list</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>FriendsSortOrder</key>
     <map>
       <key>Comment</key>
@@ -10471,6 +10504,17 @@
       <key>Value</key>
       <real>90.0</real>
     </map>
+    <key>YouAreHereDistance</key>
+    <map>
+      <key>Comment</key>
+      <string>Radius of distance for banner that indicates if the resident is "on" the Place.(meters from avatar to requested place)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>10.0</real>
+    </map>
     <key>YieldTime</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index f3bfa37ceaf48eb665db25f12d77850a351d5c64..c43ba27984697e50ea90a76c825c74b4603ef1c1 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -5588,6 +5588,13 @@
        local_texture="hair_grain" />
     </layer>
 
+    <layer
+       name="hair texture alpha layer"
+       visibility_mask="TRUE">
+      <texture
+         local_texture="hair_grain" />
+    </layer>
+
     <layer
        name="hair alpha"
        visibility_mask="TRUE">
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f62606cc50fede79c1ba99ccafb4ac64882aa1b8..75a72e5b17c296a42ed9240cc87cf396e885fb0f 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -42,7 +42,7 @@
 #include "lldrawable.h"
 #include "llfirstuse.h"
 #include "llfloaterreg.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
 #include "llfloatercamera.h"
 #include "llfloatercustomize.h"
 
@@ -5391,12 +5391,6 @@ void update_group_floaters(const LLUUID& group_id)
 	//*TODO Implement group update for Profile View 
 	// still actual as of July 31, 2009 (DZ)
 
-	if (gIMMgr)
-	{
-		// update the talk view
-		gIMMgr->refresh();
-	}
-
 	gAgent.fireEvent(new LLOldEvents::LLEvent(&gAgent, "new group"), "");
 }
 
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
index 1a69f1d975e81646c7ecab442fbdad06daee8081..09f7c49f23dbbc91c571aeb77af63488a6af9868 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -89,6 +89,11 @@ std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
 	return slurl;
 }
 
+//static
+BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
+{
+	return  (gAgent.getPositionAgent() - pole).length() < radius;
+}
 BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
 {
 	LLViewerRegion* region = gAgent.getRegion();
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index 47ecb04547a3eea58403d8752978f6b5ab22c447..c7aafb71e7b9db4f8b1c4c64c245963a37284df6 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -52,6 +52,11 @@ class LLAgentUI
 	static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK);
 	//build location string using a region position of the avatar. 
 	static BOOL buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region);
+	/**
+	 * @brief Check whether  the agent is in neighborhood of the pole  Within same region
+	 * @return true if the agent is in neighborhood.
+	 */
+	static BOOL checkAgentDistance(const LLVector3& local_pole, F32 radius);
 };
 
 #endif //LLAGENTUI_H
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e184d99ffc55fc1c8fa88a1cae13c944bc8b759a..06c9171d671b5ba7166af990744cc151251853e6 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -49,7 +49,6 @@
 #include "llviewerstats.h"
 #include "llmd5.h"
 #include "llpumpio.h"
-#include "llimpanel.h"
 #include "llmimetypes.h"
 #include "llslurl.h"
 #include "llstartup.h"
@@ -76,6 +75,7 @@
 #include "llteleporthistory.h"
 #include "lllocationhistory.h"
 #include "llfasttimerview.h"
+#include "llvoicechannel.h"
 
 #include "llweb.h"
 #include "llsecondlifeurls.h"
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 426fcec5141b96532473ddd8f96d3a715bd73427..65b5c86ed54302a26fc203f113642d46fcd6cf33 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -103,6 +103,8 @@ class LLAvatarIconCtrl
 	const std::string&	getFirstName() const { return mFirstName; }
 	const std::string&	getLastName() const { return mLastName; }
 
+	void setDrawTooltip(bool value) { mDrawTooltip = value;}
+
 protected:
 	LLUUID				mAvatarId;
 	std::string			mFirstName;
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 3a07c6e5efdba952109910e04ef09337beddf496..e93d0dfa50dbd45854db09b86620f3444b882f2f 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -38,6 +38,7 @@
 #include "llcallingcard.h" // for LLAvatarTracker
 #include "llcachename.h"
 #include "llvoiceclient.h"
+#include "llviewercontrol.h"	// for gSavedSettings
 
 static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
 
@@ -45,6 +46,21 @@ static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
 // Used to limit time spent for avatar list update per frame.
 static const unsigned ADD_LIMIT = 50;
 
+void LLAvatarList::toggleIcons()
+{
+	// Save the new value for new items to use.
+	mShowIcons = !mShowIcons;
+	gSavedSettings.setBOOL(mIconParamName, mShowIcons);
+	
+	// Show/hide icons for all existing items.
+	std::vector<LLPanel*> items;
+	getItems(items);
+	for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+	{
+		static_cast<LLAvatarListItem*>(*it)->setAvatarIconVisible(mShowIcons);
+	}
+}
+
 static bool findInsensitive(std::string haystack, const std::string& needle_upper)
 {
     LLStringUtil::toUpper(haystack);
@@ -73,13 +89,22 @@ LLAvatarList::LLAvatarList(const Params& p)
 	setComparator(&NAME_COMPARATOR);
 }
 
+void LLAvatarList::setShowIcons(std::string param_name)
+{
+	mIconParamName= param_name;
+	mShowIcons = gSavedSettings.getBOOL(mIconParamName);
+}
+
 // virtual
 void LLAvatarList::draw()
 {
-	if (mDirty)
-		refresh();
+	// *NOTE dzaporozhan
+	// Call refresh() after draw() to avoid flickering of avatar list items.
 
 	LLFlatListView::draw();
+
+	if (mDirty)
+		refresh();
 }
 
 void LLAvatarList::setNameFilter(const std::string& filter)
@@ -202,6 +227,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is
 	item->setContextMenu(mContextMenu);
 
 	item->childSetVisible("info_btn", false);
+	item->setAvatarIconVisible(mShowIcons);
 
 	addItem(item, id, pos);
 }
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index a83a72b26ca94ae48cd276b1a4c966c52ca0c4b1..f60f1f00f338077632a71285b9cfd2d058c1c497 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -70,7 +70,11 @@ class LLAvatarList : public LLFlatListView
 
 	void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
 
+	void toggleIcons();
 	void sortByName();
+	void setShowIcons(std::string param_name);
+	bool getIconsVisible() const { return mShowIcons; }
+	const std::string getIconParamName() const{return mIconParamName;}
 	virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
 
 protected:
@@ -86,7 +90,9 @@ class LLAvatarList : public LLFlatListView
 
 	bool mIgnoreOnlineStatus;
 	bool mDirty;
+	bool mShowIcons;
 
+	std::string				mIconParamName;
 	std::string				mNameFilter;
 	uuid_vector_t			mIDs;
 
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index ebc79aae48577fe33f41080fe673133cda1b5606..4ecb9537ba8a07bea6b4e487bc93bb5785e1fde6 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -42,6 +42,7 @@
 #include "llavatariconctrl.h"
 #include "llbutton.h"
 
+S32 LLAvatarListItem::sIconWidth = 0;
 
 LLAvatarListItem::LLAvatarListItem()
 :	LLPanel(),
@@ -55,6 +56,12 @@ LLAvatarListItem::LLAvatarListItem()
 	mOnlineStatus(E_UNKNOWN)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
+	// Remember avatar icon width including its padding from the name text box,
+	// so that we can hide and show the icon again later.
+	if (!sIconWidth)
+	{
+		sIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
+	}
 }
 
 LLAvatarListItem::~LLAvatarListItem()
@@ -188,6 +195,21 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
 	gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
 }
 
+void LLAvatarListItem::setAvatarIconVisible(bool visible)
+{
+	// Already done? Then do nothing.
+	if (mAvatarIcon->getVisible() == (BOOL)visible)
+		return;
+
+	// Show/hide avatar icon.
+	mAvatarIcon->setVisible(visible);
+
+	// Move the avatar name horizontally by icon size + its distance from the avatar name.
+	LLRect name_rect = mAvatarName->getRect();
+	name_rect.mLeft += visible ? sIconWidth : -sIconWidth;
+	mAvatarName->setRect(name_rect);
+}
+
 void LLAvatarListItem::onInfoBtnClick()
 {
 	LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarId));
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index b9cfed4b7baa52bc0536f74598ad060d0110c525..a8d391921761290e0f25f4dfc5521ec4d862e5c2 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -64,6 +64,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	void setOnline(bool online);
 	void setName(const std::string& name);
 	void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
+	void setAvatarIconVisible(bool visible);
 	
 	const LLUUID& getAvatarId() const;
 	const std::string getAvatarName() const;
@@ -87,7 +88,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 
 	void onNameCache(const std::string& first_name, const std::string& last_name);
 
-	LLAvatarIconCtrl*mAvatarIcon;
+	LLAvatarIconCtrl* mAvatarIcon;
 	LLTextBox* mAvatarName;
 	LLTextBox* mStatus;
 	
@@ -98,6 +99,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 
 	LLUUID mAvatarId;
 	EOnlineStatus mOnlineStatus;
+	static S32	sIconWidth; // icon width + padding
 };
 
 #endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index 77f941eef0ecdf72c0caf227225028f482da9abb..642742257264bbd1595b42b29c80ba9408f77b8f 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -40,6 +40,8 @@
 #include "llbottomtray.h"
 #include "llviewerwindow.h"
 #include "llrootview.h"
+#include "llsyswellwindow.h"
+#include "llfloaterreg.h"
 
 #include <algorithm>
 
@@ -128,7 +130,7 @@ void LLChannelManager::onLoginCompleted()
 	S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); 
 	S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
 	mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
-	mStartUpChannel->setShowToasts(true);
+	mStartUpChannel->setMouseDownCallback(boost::bind(&LLSysWellWindow::onStartUpToastClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window"), _2, _3, _4));
 
 	mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
 	mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 94058365beca43edc88d4a3d5a17232fa1f9020c..aaca568320d876da30ea8d722c92c3db5b1ef36f 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -38,9 +38,215 @@
 #include "llscrollcontainer.h"
 #include "llavatariconctrl.h"
 
+#include "llimview.h"
+#include "llcallingcard.h" //for LLAvatarTracker
+#include "llagentdata.h"
+#include "llavataractions.h"
+#include "lltrans.h"
+
 static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
 static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- ");
 
+std::string formatCurrentTime()
+{
+	time_t utc_time;
+	utc_time = time_corrected();
+	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
+		+LLTrans::getString("TimeMin")+"] ";
+
+	LLSD substitution;
+
+	substitution["datetime"] = (S32) utc_time;
+	LLStringUtil::format (timeStr, substitution);
+
+	return timeStr;
+}
+
+class LLChatHistoryHeader: public LLPanel
+{
+public:
+	static LLChatHistoryHeader* createInstance(const std::string& file_name)
+	{
+		LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
+		LLUICtrlFactory::getInstance()->buildPanel(pInstance, file_name);	
+		return pInstance;
+	}
+
+	BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+	{
+		return LLPanel::handleMouseUp(x,y,mask);
+	}
+
+	void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
+	{
+		std::string level = userdata.asString();
+
+		if (level == "profile")
+		{
+			LLAvatarActions::showProfile(getAvatarId());
+		}
+		else if (level == "im")
+		{
+			LLAvatarActions::startIM(getAvatarId());
+		}
+		else if (level == "add")
+		{
+			std::string name;
+			name.assign(getFirstName());
+			name.append(" ");
+			name.append(getLastName());
+
+			LLAvatarActions::requestFriendshipDialog(getAvatarId(), name);
+		}
+		else if (level == "remove")
+		{
+			LLAvatarActions::removeFriendDialog(getAvatarId());
+		}
+	}
+
+	BOOL postBuild()
+	{
+		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+		registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+
+		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+		mPopupMenuHandleAvatar = menu->getHandle();
+
+		return LLPanel::postBuild();
+	}
+
+	bool pointInChild(const std::string& name,S32 x,S32 y)
+	{
+		LLUICtrl* child = findChild<LLUICtrl>(name);
+		if(!child)
+			return false;
+		
+		LLView* parent = child->getParent();
+		if(parent!=this)
+		{
+			x-=parent->getRect().mLeft;
+			y-=parent->getRect().mBottom;
+		}
+
+		S32 local_x = x - child->getRect().mLeft ;
+		S32 local_y = y - child->getRect().mBottom ;
+		return 	child->pointInView(local_x, local_y);
+	}
+
+	BOOL handleRightMouseDown(S32 x, S32 y, MASK mask)
+	{
+		if(pointInChild("avatar_icon",x,y) || pointInChild("user_name",x,y))
+		{
+			showContextMenu(x,y);
+			return TRUE;
+		}
+
+		return LLPanel::handleRightMouseDown(x,y,mask);
+	}
+	const LLUUID&		getAvatarId () const { return mAvatarID;}
+	const std::string&	getFirstName() const { return mFirstName; }
+	const std::string&	getLastName	() const { return mLastName; }
+
+	void setup(const LLChat& chat) 
+	{
+		mAvatarID = chat.mFromID;
+		mSourceType = chat.mSourceType;
+		gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
+		if(chat.mFromID.isNull())
+		{
+			mSourceType = CHAT_SOURCE_SYSTEM;
+		}
+
+
+		LLTextBox* userName = getChild<LLTextBox>("user_name");
+		
+		if(!chat.mFromName.empty())
+			userName->setValue(chat.mFromName);
+		else
+		{
+			std::string SL = LLTrans::getString("SECOND_LIFE");
+			userName->setValue(SL);
+		}
+		
+		LLTextBox* timeBox = getChild<LLTextBox>("time_box");
+		timeBox->setValue(formatCurrentTime());
+
+		LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+
+		if(mSourceType != CHAT_SOURCE_AGENT)
+			icon->setDrawTooltip(false);
+
+		if(!chat.mFromID.isNull())
+		{
+			icon->setValue(chat.mFromID);
+		}
+
+	} 
+
+	void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
+	{
+		if (id != mAvatarID)
+			return;
+		mFirstName = first;
+		mLastName = last;
+	}
+protected:
+	void showContextMenu(S32 x,S32 y)
+	{
+		if(mSourceType == CHAT_SOURCE_SYSTEM)
+			showSystemContextMenu(x,y);
+		if(mSourceType == CHAT_SOURCE_AGENT)
+			showAvatarContextMenu(x,y);
+		if(mSourceType == CHAT_SOURCE_OBJECT)
+			showObjectContextMenu(x,y);
+	}
+
+	void showSystemContextMenu(S32 x,S32 y)
+	{
+	}
+	void showObjectContextMenu(S32 x,S32 y)
+	{
+	}
+	
+	void showAvatarContextMenu(S32 x,S32 y)
+	{
+		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get();
+
+		if(menu)
+		{
+			bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
+			
+			menu->setItemEnabled("Add Friend", !is_friend);
+			menu->setItemEnabled("Remove Friend", is_friend);
+
+			if(gAgentID == mAvatarID)
+			{
+				menu->setItemEnabled("Add Friend", false);
+				menu->setItemEnabled("Send IM", false);
+				menu->setItemEnabled("Remove Friend", false);
+			}
+
+			menu->buildDrawLabels();
+			menu->updateParent(LLMenuGL::sMenuContainer);
+			LLMenuGL::showPopup(this, menu, x, y);
+		}
+	}
+
+	
+
+protected:
+	LLHandle<LLView>	mPopupMenuHandleAvatar;
+
+	LLUUID			    mAvatarID;
+	EChatSourceType		mSourceType;
+	std::string			mFirstName;
+	std::string			mLastName;
+
+};
+
+
 LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
 : LLTextEditor(p),
 mMessageHeaderFilename(p.message_header),
@@ -48,7 +254,7 @@ mMessageSeparatorFilename(p.message_separator),
 mLeftTextPad(p.left_text_pad),
 mRightTextPad(p.right_text_pad),
 mLeftWidgetPad(p.left_widget_pad),
-mRightWidgetPad(p.rigth_widget_pad)
+mRightWidgetPad(p.right_widget_pad)
 {
 }
 
@@ -78,50 +284,49 @@ LLView* LLChatHistory::getSeparator()
 	return separator;
 }
 
-LLView* LLChatHistory::getHeader(const LLUUID& avatar_id, std::string& from, std::string& time)
+LLView* LLChatHistory::getHeader(const LLChat& chat)
 {
-	LLPanel* header = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageHeaderFilename, NULL, LLPanel::child_registry_t::instance());
-	LLTextBox* userName = header->getChild<LLTextBox>("user_name");
-	userName->setValue(from);
-	LLTextBox* timeBox = header->getChild<LLTextBox>("time_box");
-	timeBox->setValue(time);
-	if(!avatar_id.isNull())
-	{
-		LLAvatarIconCtrl* icon = header->getChild<LLAvatarIconCtrl>("avatar_icon");
-		icon->setValue(avatar_id);
-	}
+	LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
+	header->setup(chat);
 	return header;
 }
 
-void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params)
+void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params)
 {
 	LLView* view = NULL;
 	std::string view_text;
 
-	if (mLastFromName == from)
+	if (mLastFromName == chat.mFromName)
 	{
 		view = getSeparator();
 		view_text = "\n";
 	}
 	else
 	{
-		view = getHeader(avatar_id, from, time);
-		view_text = from + MESSAGE_USERNAME_DATE_SEPARATOR + time + '\n';
+		view = getHeader(chat);
+		view_text = chat.mFromName + MESSAGE_USERNAME_DATE_SEPARATOR + formatCurrentTime() + '\n';
 	}
 	//Prepare the rect for the view
 	LLRect target_rect = getDocumentView()->getRect();
-	target_rect.mLeft += mLeftWidgetPad;
+	// squeeze down the widget by subtracting padding off left and right
+	target_rect.mLeft += mLeftWidgetPad + mHPad;
 	target_rect.mRight -= mRightWidgetPad;
 	view->reshape(target_rect.getWidth(), view->getRect().getHeight());
 	view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
 
-	appendWidget(view, view_text, FALSE, TRUE, mLeftWidgetPad, 0);
+	LLInlineViewSegment::Params p;
+	p.view = view;
+	p.force_newline = true;
+	p.left_pad = mLeftWidgetPad;
+	p.right_pad = mRightWidgetPad;
+
+	appendWidget(p, view_text, false);
 
 	//Append the text message
-	message += '\n';
+	std::string message = chat.mText + '\n';
 	appendText(message, FALSE, style_params);
 
-	mLastFromName = from;
+	mLastFromName = chat.mFromName;
 	blockUndo();
 	setCursorAndScrollToEnd();
 }
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index d6eccf896af9d987ca481363d96ccfb9c53ec396..92dcfdd958265b23a8fd86289a3420fba9543773 100644
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -34,6 +34,7 @@
 #define LLCHATHISTORY_H_
 
 #include "lltexteditor.h"
+#include "llchat.h"
 
 //Chat log widget allowing addition of a message as a widget 
 class LLChatHistory : public LLTextEditor
@@ -52,7 +53,7 @@ class LLChatHistory : public LLTextEditor
 			//Widget left padding from the scroll rect
 			Optional<S32>			left_widget_pad;
 			//Widget right padding from the scroll rect
-			Optional<S32>			rigth_widget_pad;
+			Optional<S32>			right_widget_pad;
 
 			Params()
 			:	message_header("message_header"),
@@ -60,7 +61,7 @@ class LLChatHistory : public LLTextEditor
 				left_text_pad("left_text_pad"),
 				right_text_pad("right_text_pad"),
 				left_widget_pad("left_widget_pad"),
-				rigth_widget_pad("rigth_widget_pad")
+				right_widget_pad("right_widget_pad")
 				{
 				}
 
@@ -85,7 +86,7 @@ class LLChatHistory : public LLTextEditor
 		 * @param time time of a message.
 		 * @return pointer to LLView header object.
 		 */
-		LLView* getHeader(const LLUUID& avatar_id, std::string& from, std::string& time);
+		LLView* getHeader(const LLChat& chat);
 
 	public:
 		~LLChatHistory();
@@ -94,11 +95,11 @@ class LLChatHistory : public LLTextEditor
 		 * Appends a widget message.
 		 * If last user appended message, concurs with current user,
 		 * separator is added before the message, otherwise header is added.
-		 * @param from owner of a message.
+		 * @param chat - base chat message.
 		 * @param time time of a message.
 		 * @param message message itself.
 		 */
-		void appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params);
+		void appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params);
 
 	private:
 		std::string mLastFromName;
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 3b5b7f570ee839f0f0f2be8f924c894b17466289..a6afbc05bec83aca4861353577882e17b3042e38 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -503,13 +503,15 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
 		return;
 	}
 
+	LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
+
 	if (dest)
 	{
-		insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID());
+		insertBeforeItem(mItems, dest->getLandmarkId(), viewer_item);
 	}
 	else
 	{
-		mItems.push_back(gInventory.getItem(item->getUUID()));
+		mItems.push_back(viewer_item);
 	}
 
 	int sortField = 0;
@@ -534,13 +536,22 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
 		}
 	}
 
-	copy_inventory_item(
-			gAgent.getID(),
-			item->getPermissions().getOwner(),
-			item->getUUID(),
-			favorites_id,
-			std::string(),
-			cb);
+	LLToolDragAndDrop* tool_dad = LLToolDragAndDrop::getInstance();
+	if (tool_dad->getSource() == LLToolDragAndDrop::SOURCE_NOTECARD)
+	{
+		viewer_item->setType(LLAssetType::AT_FAVORITE);
+		copy_inventory_from_notecard(tool_dad->getObjectID(), tool_dad->getSourceID(), viewer_item.get(), gInventoryCallbacks.registerCB(cb));
+	}
+	else
+	{
+		copy_inventory_item(
+				gAgent.getID(),
+				item->getPermissions().getOwner(),
+				item->getUUID(),
+				favorites_id,
+				std::string(),
+				cb);
+	}
 
 	llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
 }
@@ -1263,10 +1274,9 @@ void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items,
 	items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
 }
 
-void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId)
+void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem)
 {
 	LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
-	LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId);
 
 	items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
 }
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index ea2a3d08e22424482a754df9cc9318af613ed605..e90d13f9d5157c539590574d56d1416f426b4c11 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -141,7 +141,7 @@ class LLFavoritesBarCtrl : public LLUICtrl, public LLInventoryObserver
 	 * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
 	 * this function assumes that an item identified by insertedItemId doesn't exist in items array.
 	 */
-	void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId);
+	void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem);
 
 	// finds an item by it's UUID in the items array
 	LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 92ad28a105a5e6a927087ad34fc15a2d52628cb9..63ea990d140c8d3937dad8db67e5472b526d0297 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -61,6 +61,9 @@
 #include "lluri.h"
 #include "v3dmath.h"
 #include "llwindow.h"
+#include "stringize.h"
+#include "llsdutil_math.h"
+#include "lleventdispatcher.h"
 
 #if LL_WINDOWS
 #include "lldxhardware.h"
@@ -85,6 +88,10 @@ class LLFloaterAbout
 
 public:
 	/*virtual*/ BOOL postBuild();
+
+	/// Obtain the data used to fill out the contents string. This is
+	/// separated so that we can programmatically access the same info.
+	static LLSD getInfo();
 	void onClickCopyToClipboard();
 };
 
@@ -114,25 +121,117 @@ BOOL LLFloaterAbout::postBuild()
 	getChild<LLUICtrl>("copy_btn")->setCommitCallback(
 		boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
 
-	// Version string
-	std::string version = LLTrans::getString("APP_NAME")
-		+ llformat(" %d.%d.%d (%d) %s %s (%s)\n",
-				   LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD,
-				   __DATE__, __TIME__,
-				   gSavedSettings.getString("VersionChannelName").c_str());
+#if LL_WINDOWS
+	getWindow()->incBusyCount();
+	getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+	LLSD info(getInfo());
+#if LL_WINDOWS
+	getWindow()->decBusyCount();
+	getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
 
-	std::string support;
-	support.append(version);
-	support.append("[" + get_viewer_release_notes_url() + " " +
-				   LLTrans::getString("ReleaseNotes") + "]");
-	support.append("\n\n");
+	std::ostringstream support;
 
-#if LL_MSVC
-    support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER));
-#endif
+	// Render the LLSD from getInfo() as a format_map_t
+	LLStringUtil::format_map_t args;
+	// For reasons I don't yet understand, [ReleaseNotes] is not part of the
+	// default substitution strings whereas [APP_NAME] is. But it works to
+	// simply copy it into these specific args.
+	args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes");
+	for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
+		 ii != iend; ++ii)
+	{
+		if (! ii->second.isArray())
+		{
+			// Scalar value
+			if (ii->second.isUndefined())
+			{
+				args[ii->first] = getString("none");
+			}
+			else
+			{
+				// don't forget to render value asString()
+				args[ii->first] = ii->second.asString();
+			}
+		}
+		else
+		{
+			// array value: build KEY_0, KEY_1 etc. entries
+			for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
+			{
+				args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
+			}
+		}
+	}
+
+	// Now build the various pieces
+	support << getString("AboutHeader", args);
+	if (info.has("COMPILER"))
+	{
+		support << "\n\n" << getString("AboutCompiler", args);
+	}
+	if (info.has("REGION"))
+	{
+		support << "\n\n" << getString("AboutPosition", args);
+	}
+	support << "\n\n" << getString("AboutSystem", args);
+	if (info.has("GRAPHICS_DRIVER_VERSION"))
+	{
+		support << "\n\n" << getString("AboutDriver", args);
+	}
+	support << "\n\n" << getString("AboutLibs", args);
+	if (info.has("PACKETS_IN"))
+	{
+		support << '\n' << getString("AboutTraffic", args);
+	}
 
-#if LL_GNUC
-    support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION));
+	support_widget->appendText(support.str(), 
+								FALSE, 
+								LLStyle::Params()
+									.color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+	support_widget->blockUndo();
+
+	// Fix views
+	support_widget->setCursorPos(0);
+	support_widget->setEnabled(FALSE);
+
+	credits_widget->setCursorPos(0);
+	credits_widget->setEnabled(FALSE);
+
+	return TRUE;
+}
+
+// static
+LLSD LLFloaterAbout::getInfo()
+{
+	// The point of having one method build an LLSD info block and the other
+	// construct the user-visible About string is to ensure that the same info
+	// is available to a getInfo() caller as to the user opening
+	// LLFloaterAbout.
+	LLSD info;
+	LLSD version;
+	version.append(LL_VERSION_MAJOR);
+	version.append(LL_VERSION_MINOR);
+	version.append(LL_VERSION_PATCH);
+	version.append(LL_VERSION_BUILD);
+	info["VIEWER_VERSION"] = version;
+	info["VIEWER_VERSION_STR"] = STRINGIZE(version[0].asInteger() << '.' <<
+										   version[1].asInteger() << '.' <<
+										   version[2].asInteger() << '.' <<
+										   version[3].asInteger());
+	info["BUILD_DATE"] = __DATE__;
+	info["BUILD_TIME"] = __TIME__;
+	info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
+
+	info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
+
+#if LL_MSVC
+	info["COMPILER"] = "MSVC";
+	info["COMPILER_VERSION"] = _MSC_VER;
+#elif LL_GNUC
+	info["COMPILER"] = "GCC";
+	info["COMPILER_VERSION"] = GCC_VERSION;
 #endif
 
 	// Position
@@ -140,120 +239,49 @@ BOOL LLFloaterAbout::postBuild()
 	if (region)
 	{
 		const LLVector3d &pos = gAgent.getPositionGlobal();
-		LLUIString pos_text = getString("you_are_at");
-		pos_text.setArg("[POSITION]",
-						llformat("%.1f, %.1f, %.1f ", pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ]));
-		support.append(pos_text);
-
-		LLUIString region_text = getString ("in_region") + " ";
-		region_text.setArg("[REGION]", llformat ("%s", gAgent.getRegion()->getName().c_str()));
-		support.append(region_text);
-
-		std::string buffer;
-		buffer = gAgent.getRegion()->getHost().getHostName();
-		support.append(buffer);
-		support.append(" (");
-		buffer = gAgent.getRegion()->getHost().getString();
-		support.append(buffer);
-		support.append(")\n");
-		support.append(gLastVersionChannel);
-		support.append("\n");
-		support.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) +
-					   " " + LLTrans::getString("ReleaseNotes") + "]");
-		support.append("\n\n");
+		info["POSITION"] = ll_sd_from_vector3d(pos);
+		info["REGION"] = gAgent.getRegion()->getName();
+		info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
+		info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
+		info["SERVER_VERSION"] = gLastVersionChannel;
+		info["SERVER_RELEASE_NOTES_URL"] = LLWeb::escapeURL(region->getCapability("ServerReleaseNotes"));
 	}
 
-	// *NOTE: Do not translate text like GPU, Graphics Card, etc -
-	//  Most PC users that know what these mean will be used to the english versions,
-	//  and this info sometimes gets sent to support
-	
 	// CPU
-	support.append(getString("CPU") + " ");
-	support.append( gSysCPU.getCPUString() );
-	support.append("\n");
-
-	U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
+	info["CPU"] = gSysCPU.getCPUString();
+	info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB() / 1024);
 	// Moved hack adjustment to Windows memory size into llsys.cpp
-
-	LLStringUtil::format_map_t args;
-	args["[MEM]"] = llformat ("%u", memory);
-	support.append(getString("Memory", args) + "\n");
-
-	support.append(getString("OSVersion") + " ");
-	support.append( LLAppViewer::instance()->getOSInfo().getOSString() );
-	support.append("\n");
-
-	support.append(getString("GraphicsCardVendor") + " ");
-	support.append( (const char*) glGetString(GL_VENDOR) );
-	support.append("\n");
-
-	support.append(getString("GraphicsCard") + " ");
-	support.append( (const char*) glGetString(GL_RENDERER) );
-	support.append("\n");
+	info["OS_VERSION"] = LLAppViewer::instance()->getOSInfo().getOSString();
+	info["GRAPHICS_CARD_VENDOR"] = (const char*)(glGetString(GL_VENDOR));
+	info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER));
 
 #if LL_WINDOWS
-    getWindow()->incBusyCount();
-    getWindow()->setCursor(UI_CURSOR_ARROW);
-    support.append("Windows Graphics Driver Version: ");
     LLSD driver_info = gDXHardware.getDisplayInfo();
     if (driver_info.has("DriverVersion"))
     {
-        support.append(driver_info["DriverVersion"]);
+        info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
     }
-    support.append("\n");
-    getWindow()->decBusyCount();
-    getWindow()->setCursor(UI_CURSOR_ARROW);
 #endif
 
-	support.append(getString("OpenGLVersion") + " ");
-	support.append( (const char*) glGetString(GL_VERSION) );
-	support.append("\n");
-
-	support.append("\n");
-
-	support.append(getString("LibCurlVersion") + " ");
-	support.append( LLCurl::getVersionString() );
-	support.append("\n");
-
-	support.append(getString("J2CDecoderVersion") + " ");
-	support.append( LLImageJ2C::getEngineInfo() );
-	support.append("\n");
-
-	support.append(getString("AudioDriverVersion") + " ");
+	info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
+	info["LIBCURL_VERSION"] = LLCurl::getVersionString();
+	info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
 	bool want_fullname = true;
-	support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : getString("none") );
-	support.append("\n");
+	info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
 
 	// TODO: Implement media plugin version query
-
-	support.append(getString("LLQtWebkitVersion") + " ");
-	support.append("\n");
+	info["QT_WEBKIT_VERSION"] = "4.5.2";
 
 	if (gPacketsIn > 0)
 	{
-		args["[LOST]"] = llformat ("%.0f", LLViewerStats::getInstance()->mPacketsLostStat.getCurrent());
-		args["[IN]"] = llformat ("%.0f", F32(gPacketsIn));
-		args["[PCT]"] = llformat ("%.1f", 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) );
-		support.append(getString ("PacketsLost", args) + "\n");
+		info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent();
+		info["PACKETS_IN"] = F32(gPacketsIn);
+		info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
 	}
 
-	support_widget->appendText(support, 
-								FALSE, 
-								LLStyle::Params()
-									.color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
-	support_widget->blockUndo();
-
-	// Fix views
-	support_widget->setCursorPos(0);
-	support_widget->setEnabled(FALSE);
-
-	credits_widget->setCursorPos(0);
-	credits_widget->setEnabled(FALSE);
-
-	return TRUE;
+    return info;
 }
 
-
 static std::string get_viewer_release_notes_url()
 {
 	std::ostringstream version;
@@ -272,6 +300,27 @@ static std::string get_viewer_release_notes_url()
 	return LLWeb::escapeURL(url.str());
 }
 
+class LLFloaterAboutListener: public LLDispatchListener
+{
+public:
+	LLFloaterAboutListener():
+		LLDispatchListener("LLFloaterAbout", "op")
+	{
+		add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD()));
+	}
+
+private:
+	void getInfo(const LLSD& request) const
+	{
+		LLReqID reqid(request);
+		LLSD reply(LLFloaterAbout::getInfo());
+		reqid.stamp(reply);
+		LLEventPumps::instance().obtain(request["reply"]).post(reply);
+	}
+};
+
+static LLFloaterAboutListener floaterAboutListener;
+
 void LLFloaterAbout::onClickCopyToClipboard()
 {
 	LLViewerTextEditor *support_widget = 
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index dea656b0e49d2caf2d0da56eb120188340eba1a5..fbf09207feaace624dd085a6d57f913752c249b7 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -42,7 +42,7 @@
 #include "llfloaterfriends.h"
 #include "llfloatergroups.h"
 #include "llviewercontrol.h"
-#include "llimview.h"
+#include "llvoicechannel.h"
 #include "llimpanel.h"
 
 //
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index c890f9f1226c963c48d15b1f55a1ea315a919080..a47916b7d7b591905e48e1ef2d6dba68babefb07 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1438,7 +1438,11 @@ void LLInventoryPanel::modelChanged(U32 mask)
 						}
 
 						LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
-						if (view_item->getParentFolder() != new_parent)
+
+						// added check against NULL for cases when Inventory panel contains startFolder.
+						// in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself.
+						// this check is a fix for bug EXT-1859.
+						if (NULL != new_parent && view_item->getParentFolder() != new_parent)
 						{
 							view_item->getParentFolder()->extractItem(view_item);
 							view_item->addToFolder(new_parent, mFolders);
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index b64257b11da752463cf8c58f869bb919ba0a4d56..aca9198f59ac152d0536bfa4f2e52d44d5d14bfc 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -43,7 +43,7 @@
 #include "llsliderctrl.h"
 #include "llviewercontrol.h"
 #include "llvoiceclient.h"
-#include "llimpanel.h"
+#include "llvoicechannel.h"
 
 // Library includes (after viewer)
 #include "lluictrlfactory.h"
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index a20b5ea66c0ba1d015011477fabdcb135356738f..b86795f69663911db0f4ba2830a87b23f82a2bcb 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -42,7 +42,6 @@
 #include "llchiclet.h"
 #include "llfloaterchat.h"
 #include "llfloaterreg.h"
-#include "llimview.h"
 #include "lllineeditor.h"
 #include "lllogchat.h"
 #include "llpanelimcontrolpanel.h"
@@ -50,6 +49,7 @@
 #include "lltrans.h"
 #include "llchathistory.h"
 #include "llviewerwindow.h"
+#include "llvoicechannel.h"
 #include "lltransientfloatermgr.h"
 
 
@@ -61,7 +61,14 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 	mLastMessageIndex(-1),
 	mDialog(IM_NOTHING_SPECIAL),
 	mChatHistory(NULL),
-	mInputEditor(NULL), 
+	mInputEditor(NULL),
+	mSavedTitle(),
+	mTypingStart(),
+	mShouldSendTypingState(false),
+	mMeTyping(false),
+	mOtherTyping(false),
+	mTypingTimer(),
+	mTypingTimeoutTimer(),
 	mPositioned(false),
 	mSessionInitialized(false)
 {
@@ -71,12 +78,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
 		mSessionInitialized = im_session->mSessionInitialized;
 		
 		mDialog = im_session->mType;
-		if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
-		{
+		switch(mDialog){
+		case IM_NOTHING_SPECIAL:
+		case IM_SESSION_P2P_INVITE:
 			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
-		}
-		else
-		{
+			break;
+		case IM_SESSION_CONFERENCE_START:
+			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+			break;
+		default:
 			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
 		}
 	}
@@ -95,6 +105,7 @@ void LLIMFloater::onFocusReceived()
 // virtual
 void LLIMFloater::onClose(bool app_quitting)
 {
+	setTyping(false);
 	gIMMgr->leaveSession(mSessionID);
 }
 
@@ -141,6 +152,7 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
 {
 	LLIMFloater* self = (LLIMFloater*) userdata;
 	self->sendMsg();
+	self->setTyping(false);
 }
 
 void LLIMFloater::sendMsg()
@@ -193,9 +205,10 @@ BOOL LLIMFloater::postBuild()
 	if (other_party_id.notNull())
 	{
 		mOtherParticipantUUID = other_party_id;
-		mControlPanel->setID(mOtherParticipantUUID);
 	}
 
+	mControlPanel->setSessionId(mSessionID);
+
 	LLButton* slide_left = getChild<LLButton>("slide_left_btn");
 	slide_left->setVisible(mControlPanel->getVisible());
 	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
@@ -228,12 +241,37 @@ BOOL LLIMFloater::postBuild()
 		LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
 	}
 
+	mTypingStart = LLTrans::getString("IM_typing_start_string");
+
+	// Disable input editor if session cannot accept text
+	LLIMModel::LLIMSession* im_session =
+		LLIMModel::instance().findIMSession(mSessionID);
+	if( im_session && !im_session->mTextIMPossible )
+	{
+		mInputEditor->setEnabled(FALSE);
+		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
+	}
+
 	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
 	//see LLFloaterIMPanel for how it is done (IB)
 
 	return LLDockableFloater::postBuild();
 }
 
+// virtual
+void LLIMFloater::draw()
+{
+	if ( mMeTyping )
+	{
+		// Time out if user hasn't typed for a while.
+		if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+		{
+			setTyping(false);
+		}
+	}
+
+	LLFloater::draw();
+}
 
 
 // static
@@ -255,6 +293,15 @@ void* LLIMFloater::createPanelGroupControl(void* userdata)
 	return self->mControlPanel;
 }
 
+// static
+void* LLIMFloater::createPanelAdHocControl(void* userdata)
+{
+	LLIMFloater *self = (LLIMFloater*)userdata;
+	self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
+	self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
+	return self->mControlPanel;
+}
+
 void LLIMFloater::onSlide()
 {
 	LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
@@ -379,10 +426,12 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
 {
 	mSessionInitialized = true;
 
+	//will be different only for an ad-hoc im session
 	if (mSessionID != im_session_id)
 	{
 		mSessionID = im_session_id;
 		setKey(im_session_id);
+		mControlPanel->setSessionId(im_session_id);
 	}
 	
 	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
@@ -402,7 +451,8 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
 
 void LLIMFloater::updateMessages()
 {
-	std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
+	std::list<LLSD> messages;
+	LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
 	std::string agent_name;
 
 	gCacheName->getFullName(gAgentID, agent_name);
@@ -428,7 +478,11 @@ void LLIMFloater::updateMessages()
 			if (from == agent_name)
 				from = LLTrans::getString("You");
 
-			mChatHistory->appendWidgetMessage(from_id, from, time, message, style_params);
+			LLChat chat(message);
+			chat.mFromID = from_id;
+			chat.mFromName = from;
+
+			mChatHistory->appendWidgetMessage(chat, style_params);
 
 			mLastMessageIndex = msg["index"].asInteger();
 		}
@@ -440,9 +494,14 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
 {
 	LLIMFloater* self= (LLIMFloater*) userdata;
 
-	//in disconnected state IM input editor should be disabled
-	self->mInputEditor->setEnabled(!gDisconnected);
-
+	// Allow enabling the LLIMFloater input editor only if session can accept text
+	LLIMModel::LLIMSession* im_session =
+		LLIMModel::instance().findIMSession(self->mSessionID);
+	if( im_session && im_session->mTextIMPossible )
+	{
+		//in disconnected state IM input editor should be disabled
+		self->mInputEditor->setEnabled(!gDisconnected);
+	}
 	self->mChatHistory->setCursorAndScrollToEnd();
 }
 
@@ -450,7 +509,7 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
 void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
 {
 	LLIMFloater* self = (LLIMFloater*) userdata;
-	self->setTyping(FALSE);
+	self->setTyping(false);
 }
 
 // static
@@ -460,19 +519,142 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
 	std::string text = self->mInputEditor->getText();
 	if (!text.empty())
 	{
-		self->setTyping(TRUE);
+		self->setTyping(true);
 	}
 	else
 	{
 		// Deleting all text counts as stopping typing.
-		self->setTyping(FALSE);
+		self->setTyping(false);
 	}
 }
 
+void LLIMFloater::setTyping(bool typing)
+{
+	if ( typing )
+	{
+		// Started or proceeded typing, reset the typing timeout timer
+		mTypingTimeoutTimer.reset();
+	}
+
+	if ( mMeTyping != typing )
+	{
+		// Typing state is changed
+		mMeTyping = typing;
+		// So, should send current state
+		mShouldSendTypingState = true;
+		// In case typing is started, send state after some delay
+		mTypingTimer.reset();
+	}
+
+	// Don't want to send typing indicators to multiple people, potentially too
+	// much network traffic. Only send in person-to-person IMs.
+	if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )
+	{
+		if ( mMeTyping )
+		{
+			if ( mTypingTimer.getElapsedTimeF32() > 1.f )
+			{
+				// Still typing, send 'start typing' notification
+				LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
+				mShouldSendTypingState = false;
+			}
+		}
+		else
+		{
+			// Send 'stop typing' notification immediately
+			LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
+			mShouldSendTypingState = false;
+		}
+	}
 
-//just a stub for now
-void LLIMFloater::setTyping(BOOL typing)
+	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+	if (speaker_mgr)
+		speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
+
+}
+
+void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
+{
+	if ( typing )
+	{
+		// other user started typing
+		addTypingIndicator(im_info);
+	}
+	else
+	{
+		// other user stopped typing
+		removeTypingIndicator(im_info);
+	}
+}
+
+void LLIMFloater::processSessionUpdate(const LLSD& session_update)
+{
+	// *TODO : verify following code when moderated mode will be implemented
+	if ( false && session_update.has("moderated_mode") &&
+		 session_update["moderated_mode"].has("voice") )
+	{
+		BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+		const std::string session_label = LLIMModel::instance().getName(mSessionID);
+
+		if (voice_moderated)
+		{
+			setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
+		}
+		else
+		{
+			setTitle(session_label);
+		}
+
+		// *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added
+		//update the speakers dropdown too
+		//mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+	}
+}
+
+void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
 {
+	// We may have lost a "stop-typing" packet, don't add it twice
+	if ( im_info && !mOtherTyping )
+	{
+		mOtherTyping = true;
+
+		// Create typing is started title string
+		LLUIString typing_start(mTypingStart);
+		typing_start.setArg("[NAME]", im_info->mName);
+
+		// Save and set new title
+		mSavedTitle = getTitle();
+		setTitle (typing_start);
+
+		// Update speaker
+		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+		if ( speaker_mgr )
+		{
+			speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);
+		}
+	}
+}
+
+void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
+{
+	if ( mOtherTyping )
+	{
+		mOtherTyping = false;
+
+		// Revert the title to saved one
+		setTitle(mSavedTitle);
+
+		if ( im_info )
+		{
+			// Update speaker
+			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+			if ( speaker_mgr )
+			{
+				speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
+			}
+		}
+
+	}
 }
 
 void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 99810b6d6ddaf5de1a7c6d3090b024551c0f72c1..3da27ac941d28ca84276abb3d1d2ee10640cf39a 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -55,6 +55,8 @@ class LLIMFloater : public LLTransientDockableFloater
 	// LLView overrides
 	/*virtual*/ BOOL postBuild();
 	/*virtual*/ void setVisible(BOOL visible);
+	// Check typing timeout timer.
+	/*virtual*/ void draw();
 
 	// LLFloater overrides
 	/*virtual*/ void onClose(bool app_quitting);
@@ -85,6 +87,8 @@ class LLIMFloater : public LLTransientDockableFloater
 	void setPositioned(bool b) { mPositioned = b; };
 
 	void onVisibilityChange(const LLSD& new_visibility);
+	void processIMTyping(const LLIMInfo* im_info, BOOL typing);
+	void processSessionUpdate(const LLSD& session_update);
 
 private:
 	// process focus events to set a currently active session
@@ -94,15 +98,21 @@ class LLIMFloater : public LLTransientDockableFloater
 	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
 	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
 	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
-	void			setTyping(BOOL typing);
+	void			setTyping(bool typing);
 	void			onSlide();
 	static void*	createPanelIMControl(void* userdata);
 	static void*	createPanelGroupControl(void* userdata);
+	static void* 	createPanelAdHocControl(void* userdata);
 	// gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111)
 	void getAllowedRect(LLRect& rect);
 
 	static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
 
+	// Add the "User is typing..." indicator.
+	void addTypingIndicator(const LLIMInfo* im_info);
+
+	// Remove the "User is typing..." indicator.
+	void removeTypingIndicator(const LLIMInfo* im_info = NULL);
 
 	LLPanelChatControlPanel* mControlPanel;
 	LLUUID mSessionID;
@@ -114,6 +124,14 @@ class LLIMFloater : public LLTransientDockableFloater
 	LLLineEditor* mInputEditor;
 	bool mPositioned;
 
+	std::string mSavedTitle;
+	LLUIString mTypingStart;
+	bool mMeTyping;
+	bool mOtherTyping;
+	bool mShouldSendTypingState;
+	LLFrameTimer mTypingTimer;
+	LLFrameTimer mTypingTimeoutTimer;
+
 	bool mSessionInitialized;
 	LLSD mQueuedMsgsForInit;
 };
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 163984f7409a6977970d135458575fb384d56140..77ee90f681298ac8cefaeb8d433e07f82e891eb7 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -54,6 +54,7 @@
 #include "llconsole.h"
 #include "llgroupactions.h"
 #include "llfloater.h"
+#include "llfloateractivespeakers.h"
 #include "llfloatercall.h"
 #include "llavataractions.h"
 #include "llimview.h"
@@ -77,6 +78,7 @@
 #include "llviewercontrol.h"
 #include "lluictrlfactory.h"
 #include "llviewerwindow.h"
+#include "llvoicechannel.h"
 #include "lllogchat.h"
 #include "llweb.h"
 #include "llhttpclient.h"
@@ -90,7 +92,6 @@
 const S32 LINE_HEIGHT = 16;
 const S32 MIN_WIDTH = 200;
 const S32 MIN_HEIGHT = 130;
-const U32 DEFAULT_RETRIES_COUNT = 3;
 
 //
 // Statics
@@ -100,831 +101,6 @@ static std::string sTitleString = "Instant Message with [NAME]";
 static std::string sTypingStartString = "[NAME]: ...";
 static std::string sSessionStartString = "Starting session with [NAME] please wait.";
 
-LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
-LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
-LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
-LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
-
-BOOL LLVoiceChannel::sSuspended = FALSE;
-
-
-
-class LLVoiceCallCapResponder : public LLHTTPClient::Responder
-{
-public:
-	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
-
-	virtual void error(U32 status, const std::string& reason);	// called with bad status codes
-	virtual void result(const LLSD& content);
-
-private:
-	LLUUID mSessionID;
-};
-
-
-void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
-{
-	llwarns << "LLVoiceCallCapResponder::error("
-		<< status << ": " << reason << ")"
-		<< llendl;
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
-	if ( channelp )
-	{
-		if ( 403 == status )
-		{
-			//403 == no ability
-			LLNotifications::instance().add(
-				"VoiceNotAllowed",
-				channelp->getNotifyArgs());
-		}
-		else
-		{
-			LLNotifications::instance().add(
-				"VoiceCallGenericError",
-				channelp->getNotifyArgs());
-		}
-		channelp->deactivate();
-	}
-}
-
-void LLVoiceCallCapResponder::result(const LLSD& content)
-{
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
-	if (channelp)
-	{
-		//*TODO: DEBUG SPAM
-		LLSD::map_const_iterator iter;
-		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
-		{
-			llinfos << "LLVoiceCallCapResponder::result got " 
-				<< iter->first << llendl;
-		}
-
-		channelp->setChannelInfo(
-			content["voice_credentials"]["channel_uri"].asString(),
-			content["voice_credentials"]["channel_credentials"].asString());
-	}
-}
-
-//
-// LLVoiceChannel
-//
-LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) : 
-	mSessionID(session_id), 
-	mState(STATE_NO_CHANNEL_INFO), 
-	mSessionName(session_name),
-	mIgnoreNextSessionLeave(FALSE)
-{
-	mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
-
-	if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
-	{
-		// a voice channel already exists for this session id, so this instance will be orphaned
-		// the end result should simply be the failure to make voice calls
-		llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
-	}
-
-	LLVoiceClient::getInstance()->addObserver(this);
-}
-
-LLVoiceChannel::~LLVoiceChannel()
-{
-	// Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
-	if(gVoiceClient)
-	{
-		gVoiceClient->removeObserver(this);
-	}
-	
-	sVoiceChannelMap.erase(mSessionID);
-	sVoiceChannelURIMap.erase(mURI);
-}
-
-void LLVoiceChannel::setChannelInfo(
-	const std::string& uri,
-	const std::string& credentials)
-{
-	setURI(uri);
-
-	mCredentials = credentials;
-
-	if (mState == STATE_NO_CHANNEL_INFO)
-	{
-		if (mURI.empty())
-		{
-			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
-			llwarns << "Received empty URI for channel " << mSessionName << llendl;
-			deactivate();
-		}
-		else if (mCredentials.empty())
-		{
-			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
-			llwarns << "Received empty credentials for channel " << mSessionName << llendl;
-			deactivate();
-		}
-		else
-		{
-			setState(STATE_READY);
-
-			// if we are supposed to be active, reconnect
-			// this will happen on initial connect, as we request credentials on first use
-			if (sCurrentVoiceChannel == this)
-			{
-				// just in case we got new channel info while active
-				// should move over to new channel
-				activate();
-			}
-		}
-	}
-}
-
-void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
-	if (channelURI != mURI)
-	{
-		return;
-	}
-
-	if (type < BEGIN_ERROR_STATUS)
-	{
-		handleStatusChange(type);
-	}
-	else
-	{
-		handleError(type);
-	}
-}
-
-void LLVoiceChannel::handleStatusChange(EStatusType type)
-{
-	// status updates
-	switch(type)
-	{
-	case STATUS_LOGIN_RETRY:
-		//mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
-		LLNotifications::instance().add("VoiceLoginRetry");
-		break;
-	case STATUS_LOGGED_IN:
-		//if (!mLoginNotificationHandle.isDead())
-		//{
-		//	LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
-		//	if (notifyp)
-		//	{
-		//		notifyp->close();
-		//	}
-		//	mLoginNotificationHandle.markDead();
-		//}
-		break;
-	case STATUS_LEFT_CHANNEL:
-		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
-		{
-			// if forceably removed from channel
-			// update the UI and revert to default channel
-			LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
-			deactivate();
-		}
-		mIgnoreNextSessionLeave = FALSE;
-		break;
-	case STATUS_JOINING:
-		if (callStarted())
-		{
-			setState(STATE_RINGING);
-		}
-		break;
-	case STATUS_JOINED:
-		if (callStarted())
-		{
-			setState(STATE_CONNECTED);
-		}
-	default:
-		break;
-	}
-}
-
-// default behavior is to just deactivate channel
-// derived classes provide specific error messages
-void LLVoiceChannel::handleError(EStatusType type)
-{
-	deactivate();
-	setState(STATE_ERROR);
-}
-
-BOOL LLVoiceChannel::isActive()
-{ 
-	// only considered active when currently bound channel matches what our channel
-	return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI; 
-}
-
-BOOL LLVoiceChannel::callStarted()
-{
-	return mState >= STATE_CALL_STARTED;
-}
-
-void LLVoiceChannel::deactivate()
-{
-	if (mState >= STATE_RINGING)
-	{
-		// ignore session leave event
-		mIgnoreNextSessionLeave = TRUE;
-	}
-
-	if (callStarted())
-	{
-		setState(STATE_HUNG_UP);
-		// mute the microphone if required when returning to the proximal channel
-		if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
-		{
-			gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
-		}
-	}
-
-	if (sCurrentVoiceChannel == this)
-	{
-		// default channel is proximal channel
-		sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
-		sCurrentVoiceChannel->activate();
-	}
-}
-
-void LLVoiceChannel::activate()
-{
-	if (callStarted())
-	{
-		return;
-	}
-
-	// deactivate old channel and mark ourselves as the active one
-	if (sCurrentVoiceChannel != this)
-	{
-		// mark as current before deactivating the old channel to prevent
-		// activating the proximal channel between IM calls
-		LLVoiceChannel* old_channel = sCurrentVoiceChannel;
-		sCurrentVoiceChannel = this;
-		if (old_channel)
-		{
-			old_channel->deactivate();
-		}
-	}
-
-	if (mState == STATE_NO_CHANNEL_INFO)
-	{
-		// responsible for setting status to active
-		getChannelInfo();
-	}
-	else
-	{
-		setState(STATE_CALL_STARTED);
-	}
-}
-
-void LLVoiceChannel::getChannelInfo()
-{
-	// pretend we have everything we need
-	if (sCurrentVoiceChannel == this)
-	{
-		setState(STATE_CALL_STARTED);
-	}
-}
-
-//static 
-LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
-{
-	voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
-	if (found_it == sVoiceChannelMap.end())
-	{
-		return NULL;
-	}
-	else
-	{
-		return found_it->second;
-	}
-}
-
-//static 
-LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
-{
-	voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
-	if (found_it == sVoiceChannelURIMap.end())
-	{
-		return NULL;
-	}
-	else
-	{
-		return found_it->second;
-	}
-}
-
-void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
-{
-	sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
-	mSessionID = new_session_id;
-	sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
-}
-
-void LLVoiceChannel::setURI(std::string uri)
-{
-	sVoiceChannelURIMap.erase(mURI);
-	mURI = uri;
-	sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
-}
-
-void LLVoiceChannel::setState(EState state)
-{
-	switch(state)
-	{
-	case STATE_RINGING:
-		gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
-		break;
-	case STATE_CONNECTED:
-		gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
-		break;
-	case STATE_HUNG_UP:
-		gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
-		break;
-	default:
-		break;
-	}
-
-	mState = state;
-}
-
-void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
-{
-	if (state == STATE_CONNECTED)
-	{
-		LLFloaterReg::showInstance("voice_call", mSessionID);
-	}
-	// By checking that current state is CONNECTED we make sure that the call window
-	// has been shown, hence there's something to hide. This helps when user presses
-	// the "End call" button right after initiating the call.
-	// *TODO: move this check to LLFloaterCall?
-	else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
-	{
-		LLFloaterReg::hideInstance("voice_call", mSessionID);
-	}
-}
-
-//static
-void LLVoiceChannel::initClass()
-{
-	sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
-}
-
-
-//static 
-void LLVoiceChannel::suspend()
-{
-	if (!sSuspended)
-	{
-		sSuspendedVoiceChannel = sCurrentVoiceChannel;
-		sSuspended = TRUE;
-	}
-}
-
-//static 
-void LLVoiceChannel::resume()
-{
-	if (sSuspended)
-	{
-		if (gVoiceClient->voiceEnabled())
-		{
-			if (sSuspendedVoiceChannel)
-			{
-				sSuspendedVoiceChannel->activate();
-			}
-			else
-			{
-				LLVoiceChannelProximal::getInstance()->activate();
-			}
-		}
-		sSuspended = FALSE;
-	}
-}
-
-
-//
-// LLVoiceChannelGroup
-//
-
-LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) : 
-	LLVoiceChannel(session_id, session_name)
-{
-	mRetries = DEFAULT_RETRIES_COUNT;
-	mIsRetrying = FALSE;
-}
-
-void LLVoiceChannelGroup::deactivate()
-{
-	if (callStarted())
-	{
-		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
-	}
-	LLVoiceChannel::deactivate();
-}
-
-void LLVoiceChannelGroup::activate()
-{
-	if (callStarted()) return;
-
-	LLVoiceChannel::activate();
-
-	if (callStarted())
-	{
-		// we have the channel info, just need to use it now
-		LLVoiceClient::getInstance()->setNonSpatialChannel(
-			mURI,
-			mCredentials);
-
-#if 0 // *TODO
-		if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
-		{
-			// Add the party to the list of people with which we've recently interacted.
-			for (/*people in the chat*/)
-				LLRecentPeople::instance().add(buddy_id);
-		}
-#endif
-	}
-}
-
-void LLVoiceChannelGroup::getChannelInfo()
-{
-	LLViewerRegion* region = gAgent.getRegion();
-	if (region)
-	{
-		std::string url = region->getCapability("ChatSessionRequest");
-		LLSD data;
-		data["method"] = "call";
-		data["session-id"] = mSessionID;
-		LLHTTPClient::post(url,
-						   data,
-						   new LLVoiceCallCapResponder(mSessionID));
-	}
-}
-
-void LLVoiceChannelGroup::setChannelInfo(
-	const std::string& uri,
-	const std::string& credentials)
-{
-	setURI(uri);
-
-	mCredentials = credentials;
-
-	if (mState == STATE_NO_CHANNEL_INFO)
-	{
-		if(!mURI.empty() && !mCredentials.empty())
-		{
-			setState(STATE_READY);
-
-			// if we are supposed to be active, reconnect
-			// this will happen on initial connect, as we request credentials on first use
-			if (sCurrentVoiceChannel == this)
-			{
-				// just in case we got new channel info while active
-				// should move over to new channel
-				activate();
-			}
-		}
-		else
-		{
-			//*TODO: notify user
-			llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
-			deactivate();
-		}
-	}
-	else if ( mIsRetrying )
-	{
-		// we have the channel info, just need to use it now
-		LLVoiceClient::getInstance()->setNonSpatialChannel(
-			mURI,
-			mCredentials);
-	}
-}
-
-void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
-{
-	// status updates
-	switch(type)
-	{
-	case STATUS_JOINED:
-		mRetries = 3;
-		mIsRetrying = FALSE;
-	default:
-		break;
-	}
-
-	LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelGroup::handleError(EStatusType status)
-{
-	std::string notify;
-	switch(status)
-	{
-	case ERROR_CHANNEL_LOCKED:
-	case ERROR_CHANNEL_FULL:
-		notify = "VoiceChannelFull";
-		break;
-	case ERROR_NOT_AVAILABLE:
-		//clear URI and credentials
-		//set the state to be no info
-		//and activate
-		if ( mRetries > 0 )
-		{
-			mRetries--;
-			mIsRetrying = TRUE;
-			mIgnoreNextSessionLeave = TRUE;
-
-			getChannelInfo();
-			return;
-		}
-		else
-		{
-			notify = "VoiceChannelJoinFailed";
-			mRetries = DEFAULT_RETRIES_COUNT;
-			mIsRetrying = FALSE;
-		}
-
-		break;
-
-	case ERROR_UNKNOWN:
-	default:
-		break;
-	}
-
-	// notification
-	if (!notify.empty())
-	{
-		LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
-		// echo to im window
-		gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
-	}
-
-	LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelGroup::setState(EState state)
-{
-	// HACK: Open/close the call window if needed.
-	toggleCallWindowIfNeeded(state);
-
-	switch(state)
-	{
-	case STATE_RINGING:
-		if ( !mIsRetrying )
-		{
-			gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
-		}
-
-		mState = state;
-		break;
-	default:
-		LLVoiceChannel::setState(state);
-	}
-}
-
-//
-// LLVoiceChannelProximal
-//
-LLVoiceChannelProximal::LLVoiceChannelProximal() : 
-	LLVoiceChannel(LLUUID::null, LLStringUtil::null)
-{
-	activate();
-}
-
-BOOL LLVoiceChannelProximal::isActive()
-{
-	return callStarted() && LLVoiceClient::getInstance()->inProximalChannel(); 
-}
-
-void LLVoiceChannelProximal::activate()
-{
-	if (callStarted()) return;
-
-	LLVoiceChannel::activate();
-
-	if (callStarted())
-	{
-		// this implicitly puts you back in the spatial channel
-		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
-	}
-}
-
-void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
-	if (!proximal)
-	{
-		return;
-	}
-
-	if (type < BEGIN_ERROR_STATUS)
-	{
-		handleStatusChange(type);
-	}
-	else
-	{
-		handleError(type);
-	}
-}
-
-void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
-{
-	// status updates
-	switch(status)
-	{
-	case STATUS_LEFT_CHANNEL:
-		// do not notify user when leaving proximal channel
-		return;
-	case STATUS_VOICE_DISABLED:
-		 gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
-		return;
-	default:
-		break;
-	}
-	LLVoiceChannel::handleStatusChange(status);
-}
-
-
-void LLVoiceChannelProximal::handleError(EStatusType status)
-{
-	std::string notify;
-	switch(status)
-	{
-	  case ERROR_CHANNEL_LOCKED:
-	  case ERROR_CHANNEL_FULL:
-		notify = "ProximalVoiceChannelFull";
-		break;
-	  default:
-		 break;
-	}
-
-	// notification
-	if (!notify.empty())
-	{
-		LLNotifications::instance().add(notify, mNotifyArgs);
-	}
-
-	LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelProximal::deactivate()
-{
-	if (callStarted())
-	{
-		setState(STATE_HUNG_UP);
-	}
-}
-
-
-//
-// LLVoiceChannelP2P
-//
-LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) : 
-		LLVoiceChannelGroup(session_id, session_name), 
-		mOtherUserID(other_user_id),
-		mReceivedCall(FALSE)
-{
-	// make sure URI reflects encoded version of other user's agent id
-	setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
-}
-
-void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
-{
-	// status updates
-	switch(type)
-	{
-	case STATUS_LEFT_CHANNEL:
-		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
-		{
-			if (mState == STATE_RINGING)
-			{
-				// other user declined call
-				LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
-			}
-			else
-			{
-				// other user hung up
-				LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
-			}
-			deactivate();
-		}
-		mIgnoreNextSessionLeave = FALSE;
-		return;
-	default:
-		break;
-	}
-
-	LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelP2P::handleError(EStatusType type)
-{
-	switch(type)
-	{
-	case ERROR_NOT_AVAILABLE:
-		LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
-		break;
-	default:
-		break;
-	}
-
-	LLVoiceChannel::handleError(type);
-}
-
-void LLVoiceChannelP2P::activate()
-{
-	if (callStarted()) return;
-
-	LLVoiceChannel::activate();
-
-	if (callStarted())
-	{
-		// no session handle yet, we're starting the call
-		if (mSessionHandle.empty())
-		{
-			mReceivedCall = FALSE;
-			LLVoiceClient::getInstance()->callUser(mOtherUserID);
-		}
-		// otherwise answering the call
-		else
-		{
-			LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
-			
-			// using the session handle invalidates it.  Clear it out here so we can't reuse it by accident.
-			mSessionHandle.clear();
-		}
-
-		// Add the party to the list of people with which we've recently interacted.
-		LLRecentPeople::instance().add(mOtherUserID);
-	}
-}
-
-void LLVoiceChannelP2P::getChannelInfo()
-{
-	// pretend we have everything we need, since P2P doesn't use channel info
-	if (sCurrentVoiceChannel == this)
-	{
-		setState(STATE_CALL_STARTED);
-	}
-}
-
-// receiving session from other user who initiated call
-void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
-{ 
-	BOOL needs_activate = FALSE;
-	if (callStarted())
-	{
-		// defer to lower agent id when already active
-		if (mOtherUserID < gAgent.getID())
-		{
-			// pretend we haven't started the call yet, so we can connect to this session instead
-			deactivate();
-			needs_activate = TRUE;
-		}
-		else
-		{
-			// we are active and have priority, invite the other user again
-			// under the assumption they will join this new session
-			mSessionHandle.clear();
-			LLVoiceClient::getInstance()->callUser(mOtherUserID);
-			return;
-		}
-	}
-
-	mSessionHandle = handle;
-
-	// The URI of a p2p session should always be the other end's SIP URI.
-	if(!inURI.empty())
-	{
-		setURI(inURI);
-	}
-	else
-	{
-		setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
-	}
-	
-	mReceivedCall = TRUE;
-
-	if (needs_activate)
-	{
-		activate();
-	}
-}
-
-void LLVoiceChannelP2P::setState(EState state)
-{
-	// HACK: Open/close the call window if needed.
-	toggleCallWindowIfNeeded(state);
-
-	// you only "answer" voice invites in p2p mode
-	// so provide a special purpose message here
-	if (mReceivedCall && state == STATE_RINGING)
-	{
-		gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
-		mState = state;
-		return;
-	}
-	LLVoiceChannel::setState(state);
-}
-
 
 //
 // LLFloaterIMPanel
@@ -1836,75 +1012,8 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string
 	self->mHistoryEditor->blockUndo();
 }
 
-void LLFloaterIMPanel::showSessionStartError(
-	const std::string& error_string)
-{
-	LLSD args;
-	args["REASON"] = LLTrans::getString(error_string);
-	args["RECIPIENT"] = getTitle();
-
-	LLSD payload;
-	payload["session_id"] = mSessionUUID;
-
-	LLNotifications::instance().add(
-		"ChatterBoxSessionStartError",
-		args,
-		payload,
-		onConfirmForceCloseError);
-}
-
-void LLFloaterIMPanel::showSessionEventError(
-	const std::string& event_string,
-	const std::string& error_string)
-{
-	LLSD args;
-	args["REASON"] =
-		LLTrans::getString(error_string);
-	args["EVENT"] =
-		LLTrans::getString(event_string);
-	args["RECIPIENT"] = getTitle();
-
-	LLNotifications::instance().add(
-		"ChatterBoxSessionEventError",
-		args);
-}
-
-void LLFloaterIMPanel::showSessionForceClose(
-	const std::string& reason_string)
-{
-	LLSD args;
-
-	args["NAME"] = getTitle();
-	args["REASON"] = LLTrans::getString(reason_string);
-
-	LLSD payload;
-	payload["session_id"] = mSessionUUID;
-
-	LLNotifications::instance().add(
-		"ForceCloseChatterBoxSession",
-		args,
-		payload,
-		LLFloaterIMPanel::onConfirmForceCloseError);
-
-}
-
 //static 
 void LLFloaterIMPanel::onKickSpeaker(void* user_data)
 {
 
 }
-
-bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const LLSD& response)
-{
-	//only 1 option really
-	LLUUID session_id = notification["payload"]["session_id"];
-
-	if ( gIMMgr )
-	{
-		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(
-			session_id);
-
-		if ( floaterp ) floaterp->closeFloater(FALSE);
-	}
-	return false;
-}
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 4e306c7fabfeb5a882921a7c3d78788677ceacc3..39107d9a227bbdcd3ede0bbf52a5b40bd3be2754 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -50,133 +50,6 @@ class LLIMSpeakerMgr;
 class LLPanelActiveSpeakers;
 class LLPanelChatControlPanel;
 
-class LLVoiceChannel : public LLVoiceClientStatusObserver
-{
-public:
-	typedef enum e_voice_channel_state
-	{
-		STATE_NO_CHANNEL_INFO,
-		STATE_ERROR,
-		STATE_HUNG_UP,
-		STATE_READY,
-		STATE_CALL_STARTED,
-		STATE_RINGING,
-		STATE_CONNECTED
-	} EState;
-
-	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
-	virtual ~LLVoiceChannel();
-
-	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-
-	virtual void handleStatusChange(EStatusType status);
-	virtual void handleError(EStatusType status);
-	virtual void deactivate();
-	virtual void activate();
-	virtual void setChannelInfo(
-		const std::string& uri,
-		const std::string& credentials);
-	virtual void getChannelInfo();
-	virtual BOOL isActive();
-	virtual BOOL callStarted();
-	const std::string& getSessionName() const { return mSessionName; }
-
-	const LLUUID getSessionID() { return mSessionID; }
-	EState getState() { return mState; }
-
-	void updateSessionID(const LLUUID& new_session_id);
-	const LLSD& getNotifyArgs() { return mNotifyArgs; }
-
-	static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
-	static LLVoiceChannel* getChannelByURI(std::string uri);
-	static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
-	static void initClass();
-	
-	static void suspend();
-	static void resume();
-
-protected:
-	virtual void setState(EState state);
-	void toggleCallWindowIfNeeded(EState state);
-	void setURI(std::string uri);
-
-	std::string	mURI;
-	std::string	mCredentials;
-	LLUUID		mSessionID;
-	EState		mState;
-	std::string	mSessionName;
-	LLSD mNotifyArgs;
-	BOOL		mIgnoreNextSessionLeave;
-	LLHandle<LLPanel> mLoginNotificationHandle;
-
-	typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
-	static voice_channel_map_t sVoiceChannelMap;
-
-	typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
-	static voice_channel_map_uri_t sVoiceChannelURIMap;
-
-	static LLVoiceChannel* sCurrentVoiceChannel;
-	static LLVoiceChannel* sSuspendedVoiceChannel;
-	static BOOL sSuspended;
-};
-
-class LLVoiceChannelGroup : public LLVoiceChannel
-{
-public:
-	LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
-
-	/*virtual*/ void handleStatusChange(EStatusType status);
-	/*virtual*/ void handleError(EStatusType status);
-	/*virtual*/ void activate();
-	/*virtual*/ void deactivate();
-	/*vritual*/ void setChannelInfo(
-		const std::string& uri,
-		const std::string& credentials);
-	/*virtual*/ void getChannelInfo();
-
-protected:
-	virtual void setState(EState state);
-
-private:
-	U32 mRetries;
-	BOOL mIsRetrying;
-};
-
-class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
-{
-public:
-	LLVoiceChannelProximal();
-
-	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-	/*virtual*/ void handleStatusChange(EStatusType status);
-	/*virtual*/ void handleError(EStatusType status);
-	/*virtual*/ BOOL isActive();
-	/*virtual*/ void activate();
-	/*virtual*/ void deactivate();
-
-};
-
-class LLVoiceChannelP2P : public LLVoiceChannelGroup
-{
-public:
-	LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
-
-	/*virtual*/ void handleStatusChange(EStatusType status);
-	/*virtual*/ void handleError(EStatusType status);
-    /*virtual*/ void activate();
-	/*virtual*/ void getChannelInfo();
-
-	void setSessionHandle(const std::string& handle, const std::string &inURI);
-
-protected:
-	virtual void setState(EState state);
-
-private:
-	std::string	mSessionHandle;
-	LLUUID		mOtherUserID;
-	BOOL		mReceivedCall;
-};
-
 class LLFloaterIMPanel : public LLFloater
 {
 public:
@@ -256,15 +129,6 @@ class LLFloaterIMPanel : public LLFloater
 	void processIMTyping(const LLIMInfo* im_info, BOOL typing);
 	static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
 
-	//show error statuses to the user
-	void showSessionStartError(const std::string& error_string);
-	void showSessionEventError(
-		const std::string& event_string,
-		const std::string& error_string);
-	void showSessionForceClose(const std::string& reason);
-
-	static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
-
 private:
 	// Called by UI methods.
 	void sendMsg();
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index b631c991aeba155592d74ebd35d2500eb18d9eb0..8a55ab41b9162f515243ea29287d44ababb7a0d8 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -70,6 +70,7 @@
 #include "llviewerwindow.h"
 #include "llnotify.h"
 #include "llviewerregion.h"
+#include "llvoicechannel.h"
 #include "lltrans.h"
 #include "llrecentpeople.h"
 
@@ -144,7 +145,10 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
 	mInitialTargetIDs(ids),
 	mVoiceChannel(NULL),
 	mSpeakers(NULL),
-	mSessionInitialized(false)
+	mSessionInitialized(false),
+	mCallBackEnabled(true),
+	mTextIMPossible(true),
+	mOtherParticipantIsAvatar(true)
 {
 	if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
 	{
@@ -168,6 +172,13 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
 		//so we're already initialized
 		mSessionInitialized = true;
 	}
+
+	if (IM_NOTHING_SPECIAL == type)
+	{
+		mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID);
+		mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
+		mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
+	}
 }
 
 LLIMModel::LLIMSession::~LLIMSession()
@@ -272,7 +283,8 @@ void LLIMModel::testMessages()
 }
 
 
-bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, const std::vector<LLUUID>& ids)
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, 
+						   const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
 {
 	if (is_in_map(sSessionsMap, session_id))
 	{
@@ -289,7 +301,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage
 
 }
 
-bool LLIMModel::clearSession(LLUUID session_id)
+bool LLIMModel::clearSession(const LLUUID& session_id)
 {
 	if (sSessionsMap.find(session_id) == sSessionsMap.end()) return false;
 	delete (sSessionsMap[session_id]);
@@ -297,16 +309,13 @@ bool LLIMModel::clearSession(LLUUID session_id)
 	return true;
 }
 
-//*TODO remake it, instead of returing the list pass it as as parameter (IB)
-std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
 {
-	std::list<LLSD> return_list;
-
 	LLIMSession* session = findIMSession(session_id);
 	if (!session) 
 	{
 		llwarns << "session " << session_id << "does not exist " << llendl;
-		return return_list;
+		return;
 	}
 
 	int i = session->mMsgs.size() - start_index;
@@ -317,7 +326,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
 	{
 		LLSD msg;
 		msg = *iter;
-		return_list.push_back(*iter);
+		messages.push_back(*iter);
 		i--;
 	}
 
@@ -327,14 +336,9 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
 	arg["session_id"] = session_id;
 	arg["num_unread"] = 0;
 	mNoUnreadMsgsSignal(arg);
-
-    // TODO: in the future is there a more efficient way to return these
-	//of course there is - return as parameter (IB)
-	return return_list;
-
 }
 
-bool LLIMModel::addToHistory(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text) { 
+bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
 	
 	LLIMSession* session = findIMSession(session_id);
 
@@ -383,8 +387,8 @@ bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, con
 	return false;
 }
 
-//*TODO add const qualifier and pass by references (IB)
-bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text, bool log2file /* = true */) { 
+bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, 
+						   const std::string& utf8_text, bool log2file /* = true */) { 
 	LLIMSession* session = findIMSession(session_id);
 
 	if (!session) 
@@ -506,7 +510,7 @@ void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id,
 	gAgent.sendReliableMessage();
 }
 
-void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id) 
+void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
 {
 	if(session_id.notNull())
 	{
@@ -890,20 +894,11 @@ class LLViewerChatterBoxInvitationAcceptResponder :
 		{
 			gIMMgr->clearPendingAgentListUpdates(mSessionID);
 			gIMMgr->clearPendingInvitation(mSessionID);
-
-			LLFloaterIMPanel* floaterp =
-				gIMMgr->findFloaterBySession(mSessionID);
-
-			if ( floaterp )
+			if ( 404 == statusNum )
 			{
-				if ( 404 == statusNum )
-				{
-					std::string error_string;
-					error_string = "does not exist";
-
-					floaterp->showSessionStartError(
-						error_string);
-				}
+				std::string error_string;
+				error_string = "does not exist";
+				gIMMgr->showSessionStartError(error_string, mSessionID);
 			}
 		}
 	}
@@ -955,6 +950,106 @@ LLUUID LLIMMgr::computeSessionID(
 	return session_id;
 }
 
+inline LLFloater* getFloaterBySessionID(const LLUUID session_id)
+{
+	LLFloater* floater = NULL;
+	if ( gIMMgr )
+	{
+		floater = dynamic_cast < LLFloater* >
+			( gIMMgr->findFloaterBySession(session_id) );
+	}
+	if ( !floater )
+	{
+		floater = dynamic_cast < LLFloater* >
+			( LLIMFloater::findInstance(session_id) );
+	}
+	return floater;
+}
+
+void
+LLIMMgr::showSessionStartError(
+	const std::string& error_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+	args["REASON"] = LLTrans::getString(error_string);
+	args["RECIPIENT"] = floater->getTitle();
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+
+	LLNotifications::instance().add(
+		"ChatterBoxSessionStartError",
+		args,
+		payload,
+		LLIMMgr::onConfirmForceCloseError);
+}
+
+void
+LLIMMgr::showSessionEventError(
+	const std::string& event_string,
+	const std::string& error_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+	args["REASON"] =
+		LLTrans::getString(error_string);
+	args["EVENT"] =
+		LLTrans::getString(event_string);
+	args["RECIPIENT"] = floater->getTitle();
+
+	LLNotifications::instance().add(
+		"ChatterBoxSessionEventError",
+		args);
+}
+
+void
+LLIMMgr::showSessionForceClose(
+	const std::string& reason_string,
+	const LLUUID session_id)
+{
+	const LLFloater* floater = getFloaterBySessionID (session_id);
+	if (!floater) return;
+
+	LLSD args;
+
+	args["NAME"] = floater->getTitle();
+	args["REASON"] = LLTrans::getString(reason_string);
+
+	LLSD payload;
+	payload["session_id"] = session_id;
+
+	LLNotifications::instance().add(
+		"ForceCloseChatterBoxSession",
+		args,
+		payload,
+		LLIMMgr::onConfirmForceCloseError);
+}
+
+//static
+bool
+LLIMMgr::onConfirmForceCloseError(
+	const LLSD& notification,
+	const LLSD& response)
+{
+	//only 1 option really
+	LLUUID session_id = notification["payload"]["session_id"];
+
+	LLFloater* floater = getFloaterBySessionID (session_id);
+	if ( floater )
+	{
+		floater->closeFloater(FALSE);
+	}
+	return false;
+}
+
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLIncomingCallDialog
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1114,29 +1209,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
 	}
 }
 
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLIMViewFriendObserver
-//
-// Bridge to suport knowing when the inventory has changed.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLIMViewFriendObserver : public LLFriendObserver
-{
-public:
-	LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {}
-	virtual ~LLIMViewFriendObserver() {}
-	virtual void changed(U32 mask)
-	{
-		if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
-		{
-			mTV->refresh();
-		}
-	}
-protected:
-	LLIMMgr* mTV;
-};
-
-
 bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 {
 	const LLSD& payload = notification["payload"];
@@ -1237,7 +1309,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 //
 
 LLIMMgr::LLIMMgr() :
-	mFriendObserver(NULL),
 	mIMReceived(FALSE)
 {
 	static bool registered_dialog = false;
@@ -1246,21 +1317,11 @@ LLIMMgr::LLIMMgr() :
 		LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
 		registered_dialog = true;
 	}
-		
-	mFriendObserver = new LLIMViewFriendObserver(this);
-	LLAvatarTracker::instance().addObserver(mFriendObserver);
 
 	mPendingInvitations = LLSD::emptyMap();
 	mPendingAgentListUpdates = LLSD::emptyMap();
 }
 
-LLIMMgr::~LLIMMgr()
-{
-	LLAvatarTracker::instance().removeObserver(mFriendObserver);
-	delete mFriendObserver;
-	// Children all cleaned up by default view destructor.
-}
-
 // Add a message to a session. 
 void LLIMMgr::addMessage(
 	const LLUUID& session_id,
@@ -1299,9 +1360,15 @@ void LLIMMgr::addMessage(
 		fixed_session_name = session_name;
 	}
 
-	if (!LLIMModel::getInstance()->findIMSession(new_session_id))
+	bool new_session = !hasSession(session_id);
+	if (new_session)
 	{
-		LLIMModel::getInstance()->newSession(session_id, fixed_session_name, dialog, other_participant_id);
+		// *NOTE dzaporozhan
+		// Workaround for critical bug EXT-1918
+
+		// *TODO 
+		// Investigate cases when session_id == NULL and find solution to handle those cases
+		LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id);
 	}
 
 	floater = findFloaterBySession(new_session_id);
@@ -1318,15 +1385,16 @@ void LLIMMgr::addMessage(
 	// create IM window as necessary
 	if(!floater)
 	{
-
-		
 		floater = createFloater(
 			new_session_id,
 			other_participant_id,
 			fixed_session_name,
 			dialog,
 			FALSE);
+	}
 
+	if (new_session)
+	{
 		// When we get a new IM, and if you are a god, display a bit
 		// of information about the source. This is to help liaisons
 		// when answering questions.
@@ -1336,7 +1404,7 @@ void LLIMMgr::addMessage(
 			std::ostringstream bonus_info;
 			bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
 				<< parent_estate_id
-			<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+				<< ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
 				<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
 
 			// once we have web-services (or something) which returns
@@ -1439,10 +1507,7 @@ S32 LLIMMgr::getNumberOfUnreadIM()
 	S32 num = 0;
 	for(it = LLIMModel::sSessionsMap.begin(); it != LLIMModel::sSessionsMap.end(); ++it)
 	{
-		if((*it).first != mBeingRemovedSessionID)
-		{
-			num += (*it).second->mNumUnread;
-		}
+		num += (*it).second->mNumUnread;
 	}
 
 	return num;
@@ -1458,15 +1523,6 @@ BOOL LLIMMgr::getIMReceived() const
 	return mIMReceived;
 }
 
-// This method returns TRUE if the local viewer has a session
-// currently open keyed to the uuid. 
-BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
-{
-	LLFloaterIMPanel* floater = findFloaterBySession(uuid);
-	if(floater) return TRUE;
-	return FALSE;
-}
-
 LLUUID LLIMMgr::addP2PSession(const std::string& name,
 							const LLUUID& other_participant_id,
 							const std::string& voice_session_handle,
@@ -1560,41 +1616,25 @@ bool LLIMMgr::leaveSession(const LLUUID& session_id)
 	return true;
 }
 
-// This removes the panel referenced by the uuid, and then restores
-// internal consistency. The internal pointer is not deleted? Did you mean
-// a pointer to the corresponding LLIMSession? Session data is cleared now.
-// Put a copy of UUID to avoid problem when passed reference becames invalid
-// if it has been come from the object removed in observer.
-void LLIMMgr::removeSession(LLUUID session_id)
+// Removes data associated with a particular session specified by session_id
+void LLIMMgr::removeSession(const LLUUID& session_id)
 {
-	if (mBeingRemovedSessionID == session_id)
-	{
-		return;
-	}
+	llassert_always(hasSession(session_id));
 	
+	//*TODO remove this floater thing when Communicate Floater is being deleted (IB)
 	LLFloaterIMPanel* floater = findFloaterBySession(session_id);
 	if(floater)
 	{
 		mFloaters.erase(floater->getHandle());
 		LLFloaterChatterBox::getInstance()->removeFloater(floater);
-		//mTabContainer->removeTabPanel(floater);
-
-		clearPendingInvitation(session_id);
-		clearPendingAgentListUpdates(session_id);
 	}
 
-	// for some purposes storing ID of a sessios that is being removed
-	mBeingRemovedSessionID = session_id;
-	notifyObserverSessionRemoved(session_id);
+	clearPendingInvitation(session_id);
+	clearPendingAgentListUpdates(session_id);
 
-	//if we don't clear session data on removing the session
-	//we can't use LLBottomTray as observer of session creation/delettion and 
-	//creating chiclets only on session created even, we need to handle chiclets creation
-	//the same way as LLFloaterIMPanels were managed.
 	LLIMModel::getInstance()->clearSession(session_id);
 
-	// now this session is completely removed
-	mBeingRemovedSessionID.setNull();
+	notifyObserverSessionRemoved(session_id);
 }
 
 void LLIMMgr::inviteToSession(
@@ -1723,10 +1763,6 @@ void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::stri
 	}
 }
 
-void LLIMMgr::refresh()
-{
-}
-
 void LLIMMgr::disconnectAllSessions()
 {
 	LLFloaterIMPanel* floater = NULL;
@@ -2038,6 +2074,12 @@ void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
 	{
 		floater->processIMTyping(im_info, typing);
 	}
+
+	LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+	if ( im_floater )
+	{
+		im_floater->processIMTyping(im_info, typing);
+	}
 }
 
 class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
@@ -2087,19 +2129,21 @@ class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
 				}
 			}
 
+			LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+			if ( im_floater )
+			{
+				if ( body.has("session_info") )
+				{
+					im_floater->processSessionUpdate(body["session_info"]);
+				}
+			}
+
 			gIMMgr->clearPendingAgentListUpdates(session_id);
 		}
 		else
 		{
-			//throw an error dialog and close the temp session's
-			//floater
-			LLFloaterIMPanel* floater = 
-				gIMMgr->findFloaterBySession(temp_session_id);
-
-			if ( floater )
-			{
-				floater->showSessionStartError(body["error"].asString());
-			}
+			//throw an error dialog and close the temp session's floater
+			gIMMgr->showSessionStartError(body["error"].asString(), temp_session_id);
 		}
 
 		gIMMgr->clearPendingAgentListUpdates(session_id);
@@ -2132,15 +2176,10 @@ class LLViewerChatterBoxSessionEventReply : public LLHTTPNode
 		if ( !success )
 		{
 			//throw an error dialog
-			LLFloaterIMPanel* floater = 
-				gIMMgr->findFloaterBySession(session_id);
-
-			if (floater)
-			{
-				floater->showSessionEventError(
-					body["event"].asString(),
-					body["error"].asString());
-			}
+			gIMMgr->showSessionEventError(
+				body["event"].asString(),
+				body["error"].asString(),
+				session_id);
 		}
 	}
 };
@@ -2158,13 +2197,7 @@ class LLViewerForceCloseChatterBoxSession: public LLHTTPNode
 		session_id = input["body"]["session_id"].asUUID();
 		reason = input["body"]["reason"].asString();
 
-		LLFloaterIMPanel* floater =
-			gIMMgr ->findFloaterBySession(session_id);
-
-		if ( floater )
-		{
-			floater->showSessionForceClose(reason);
-		}
+		gIMMgr->showSessionForceClose(reason, session_id);
 	}
 };
 
@@ -2202,11 +2235,17 @@ class LLViewerChatterBoxSessionUpdate : public LLHTTPNode
 		const LLSD& context,
 		const LLSD& input) const
 	{
-		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
+		LLUUID session_id = input["body"]["session_id"].asUUID();
+		LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
 		if (floaterp)
 		{
 			floaterp->processSessionUpdate(input["body"]["info"]);
 		}
+		LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+		if ( im_floater )
+		{
+			im_floater->processSessionUpdate(input["body"]["info"]);
+		}
 	}
 };
 
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 68beb29034a15e7aca48bcf02a9ca28013b998d5..ae8fd355ea5db31904854cf7c505b7aaf3430383 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -34,7 +34,7 @@
 #define LL_LLIMVIEW_H
 
 #include "lldarray.h"
-#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr
+#include "llspeakers.h" //for LLIMSpeakerMgr
 #include "llimpanel.h" //for voice channels
 #include "llmodaldialog.h"
 #include "llinstantmessage.h"
@@ -70,6 +70,13 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 		LLIMSpeakerMgr* mSpeakers;
 
 		bool mSessionInitialized;
+
+		//true if calling back the session URI after the session has closed is possible.
+		//Currently this will be false only for PSTN P2P calls.
+		bool mCallBackEnabled;
+
+		bool mTextIMPossible;
+		bool mOtherParticipantIsAvatar;
 	};
 	
 
@@ -104,18 +111,35 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); }
 	boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); }
 
-	bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, 
+	/**
+	 * Create new session object in a model
+	 */
+	bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, 
 		const std::vector<LLUUID>& ids = std::vector<LLUUID>());
-	bool clearSession(LLUUID session_id);
-	std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0);
 
-	bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text, bool log2file = true);
-	bool addToHistory(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text); 
+	/**
+	 * Remove all session data associated with a session specified by session_id
+	 */
+	bool clearSession(const LLUUID& session_id);
 
-	bool logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text);
+	/**
+	 * Populate supplied std::list with messages starting from index specified by start_index
+	 */
+	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
 
-	//used to get the name of the session, for use as the title
-	//currently just the other avatar name
+	/**
+	 * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id
+	 * and also saved into a file if log2file is specified.
+	 * It sends new message signal for each added message.
+	 */
+	bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true);
+	
+	/**
+	 * Get a session's name. 
+	 * For a P2P chat - it's an avatar's name, 
+	 * For a group chat - it's a group's name
+	 * For an ad-hoc chat - is received from the server and is in a from of "<Avatar's name> conference"
+	 */
 	const std::string& getName(const LLUUID& session_id) const;
 
 	/** 
@@ -150,7 +174,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	*/
 	LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
 
-	static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id);
+	static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
 	static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
 						  const std::vector<LLUUID>& ids, EInstantMessage dialog);
 	static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing);
@@ -158,6 +182,19 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 								const LLUUID& other_participant_id, EInstantMessage dialog);
 
 	void testMessages();
+
+private:
+	
+	/**
+	 * Add message to a list of message associated with session specified by session_id
+	 */
+	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); 
+
+	/**
+	 * Save an IM message into a file
+	 */
+	//*TODO should also save uuid of a sender
+	bool logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text);
 };
 
 class LLIMSessionObserver
@@ -183,7 +220,7 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	};
 
 	LLIMMgr();
-	virtual ~LLIMMgr();
+	virtual ~LLIMMgr() {};
 
 	// Add a message to a session. The session can keyed to sesion id
 	// or agent id.
@@ -200,11 +237,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 
 	void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
 
-	// This method returns TRUE if the local viewer has a session
-	// currently open keyed to the uuid. The uuid can be keyed by
-	// either session id or agent id.
-	BOOL isIMSessionOpen(const LLUUID& uuid);
-
 	// This adds a session to the talk view. The name is the local
 	// name of the session, dialog specifies the type of
 	// session. Since sessions can be keyed off of first recipient or
@@ -250,9 +282,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	void processIMTypingStart(const LLIMInfo* im_info);
 	void processIMTypingStop(const LLIMInfo* im_info);
 
-	// Rebuild stuff
-	void refresh();
-
 	void notifyNewIM();
 	void clearNewIMNotification();
 
@@ -268,10 +297,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	// good connection.
 	void disconnectAllSessions();
 
-	// This is a helper function to determine what kind of im session
-	// should be used for the given agent.
-	static EInstantMessage defaultIMTypeForAgent(const LLUUID& agent_id);
-
 	BOOL hasSession(const LLUUID& session_id);
 
 	// This method returns the im panel corresponding to the uuid
@@ -290,11 +315,18 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	void clearPendingAgentListUpdates(const LLUUID& session_id);
 
 	//HACK: need a better way of enumerating existing session, or listening to session create/destroy events
+	//@deprecated, is used only by LLToolBox, which is not used anywhere, right? (IB)
 	const std::set<LLHandle<LLFloater> >& getIMFloaterHandles() { return mFloaters; }
 
 	void addSessionObserver(LLIMSessionObserver *);
 	void removeSessionObserver(LLIMSessionObserver *);
 
+	//show error statuses to the user
+	void showSessionStartError(const std::string& error_string, const LLUUID session_id);
+	void showSessionEventError(const std::string& event_string, const std::string& error_string, const LLUUID session_id);
+	void showSessionForceClose(const std::string& reason, const LLUUID session_id);
+	static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
+
 	/**
 	 * Start call in a session
 	 * @return false if voice channel doesn't exist
@@ -308,10 +340,11 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	bool endCall(const LLUUID& session_id);
 
 private:
-	// This removes the panel referenced by the uuid, and then
-	// restores internal consistency. The internal pointer is not
-	// deleted.
-	void removeSession(LLUUID session_id);
+
+	/**
+	 * Remove data associated with a particular session specified by session_id
+	 */
+	void removeSession(const LLUUID& session_id);
 
 	// create a panel and update internal representation for
 	// consistency. Returns the pointer, caller (the class instance
@@ -340,8 +373,9 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 	void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
 
 private:
+	
+	//*TODO should be deleted when Communicate Floater is being deleted
 	std::set<LLHandle<LLFloater> > mFloaters;
-	LLFriendObserver* mFriendObserver;
 
 	typedef std::list <LLIMSessionObserver *> session_observers_list_t;
 	session_observers_list_t mSessionObservers;
@@ -351,9 +385,6 @@ class LLIMMgr : public LLSingleton<LLIMMgr>
 
 	LLSD mPendingInvitations;
 	LLSD mPendingAgentListUpdates;
-	// ID of a session that is being removed: observers are already told
-	// that this session is being removed, but it is still present in the sessions' map
-	LLUUID	mBeingRemovedSessionID;
 };
 
 class LLIncomingCallDialog : public LLModalDialog
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index b36b7cf50ed3f137e46671aea4fcfd7a43c0f634..091346d3b41b7cbb524bd56f2523f07ca25d924f 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -348,7 +348,7 @@ LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID
 {
 	LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
 	if (NULL == item)
-		return false;
+		return NULL;
 
 	const LLUUID& asset_id = item->getAssetUUID();
 	return gLandmarkList.getAsset(asset_id, NULL);
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
index d6512597908a67f8aa13a6f206a0fe5f26810713..32f05e702b0943ed387e74b78906b6fdccb83709 100644
--- a/indra/newview/lllandmarkactions.h
+++ b/indra/newview/lllandmarkactions.h
@@ -108,7 +108,7 @@ class LLLandmarkActions
     /**
      * @brief Retrieve a landmark from gLandmarkList by inventory item's id
      * 
-     * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist.
+     * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.
      */
     static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID);
 
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index 3802d13f8b833bce6edce4cb31b2bc039bf0a2c7..c32ef2f22b1c7cad10ee55606a1924892b271879 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -261,6 +261,15 @@ void LLNavigationBar::draw()
 		onTeleportHistoryChanged();
 		mPurgeTPHistoryItems = false;
 	}
+
+	if (isBackgroundVisible())
+	{
+		static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
+		static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
+		gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
+                           color_drop_shadow, drop_shadow_floater );
+	}
+
 	LLPanel::draw();
 }
 
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 148f72703ce598636b47c6c7507bf0a3d92cde52..12638ab8551b6c252c8d3145c58b6eb956db3a3d 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -170,22 +170,6 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
 	return text_color;
 }
 
-std::string formatCurrentTime()
-{
-	time_t utc_time;
-	utc_time = time_corrected();
-	std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
-		+LLTrans::getString("TimeMin")+"] ";
-
-	LLSD substitution;
-
-	substitution["datetime"] = (S32) utc_time;
-	LLStringUtil::format (timeStr, substitution);
-
-	return timeStr;
-}
-
-
 void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)
 {
 	S32 font_size = gSavedSettings.getS32("ChatFontSize");
@@ -210,16 +194,14 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
 	style_params.font(fontp);
 	LLUUID uuid = chat.mFromID;
 	std::string from = chat.mFromName;
-	std::string time = formatCurrentTime();
 	std::string message = chat.mText;
-	mChatHistory->appendWidgetMessage(uuid, from, time, message, style_params);
+	mChatHistory->appendWidgetMessage(chat, style_params);
 }
 
 void	LLNearbyChat::addMessage(const LLChat& chat)
 {
 	LLColor4 color = nearbychat_get_text_color(chat);
 	
-
 	if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
 	{
 		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 5fa97926a5c02fd304dd66ce13e3a6ed21a5f05f..217007fb152b842b08463e140aec8e78c634d162 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -45,6 +45,7 @@
 #include "llviewerstats.h"
 #include "llcommandhandler.h"
 #include "llviewercontrol.h"
+#include "llnavigationbar.h"
 
 S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
 
@@ -177,6 +178,31 @@ void LLGestureComboBox::draw()
 	LLComboBox::draw();
 }
 
+//virtual
+void LLGestureComboBox::showList()
+{
+	LLComboBox::showList();
+
+	// Calculating amount of space between the navigation bar and gestures combo
+	LLNavigationBar* nb = LLNavigationBar::getInstance();
+	S32 x, nb_bottom;
+	nb->localPointToScreen(0, 0, &x, &nb_bottom);
+	
+	S32 list_bottom;
+	mList->localPointToScreen(0, 0, &x, &list_bottom);
+
+	S32 max_height = nb_bottom - list_bottom;
+
+	LLRect rect = mList->getRect();
+	// List overlapped navigation bar, downsize it
+	if (rect.getHeight() > max_height) 
+	{
+		rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), max_height);
+		mList->setRect(rect);
+		mList->reshape(rect.getWidth(), rect.getHeight());
+	}
+}
+
 LLNearbyChatBar::LLNearbyChatBar() 
 	: LLPanel()
 	, mChatBox(NULL)
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index b902ff86cc36bf14a5967cd35518cf186dddf3a1..06204e6367b4a43f5c80c03b088255e064df02a0 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -40,7 +40,7 @@
 #include "llchiclet.h"
 #include "llvoiceclient.h"
 #include "lloutputmonitorctrl.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
 
 class LLGestureComboBox
 	: public LLComboBox
@@ -62,6 +62,9 @@ class LLGestureComboBox
 	virtual void changed() { refreshGestures(); }
 
 protected:
+
+	virtual void showList();
+
 	LLFrameTimer mGestureLabelTimer;
 	std::vector<LLMultiGesture*> mGestures;
 	std::string mLabel;
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 7239f49b7f664cebd6b1960b1a879c4cab61a778..543198c1d2158c8aa62d92d54465b4a2b95c4f84 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -86,6 +86,20 @@ bool LLTipHandler::processNotification(const LLSD& notify)
 
 	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
 	{
+		// archive message in nearby chat
+		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+		if(nearby_chat)
+		{
+			LLChat chat_msg(notification->getMessage());
+			nearby_chat->addMessage(chat_msg);
+
+			// don't show toast if Nearby Chat is opened
+			if (nearby_chat->getVisible())
+			{
+				return true;
+			}			
+		}
+
 		LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
 
 		LLToast::Params p;
@@ -99,14 +113,6 @@ bool LLTipHandler::processNotification(const LLSD& notify)
 		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
 		if(channel)
 			channel->addToast(p);
-
-		// archive message in nearby chat
-		LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
-		if(nearby_chat)
-		{
-			LLChat chat_msg(notification->getMessage());
-			nearby_chat->addMessage(chat_msg);
-		}
 	}
 	else if (notify["sigtype"].asString() == "delete")
 	{
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 6eed956eb840e11730e44340f2e05b3db13aea18..f9eeaf1e9e3e237fb7ddbf0946f862d852dbda62 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -34,6 +34,7 @@
 
 #include "llpanelimcontrolpanel.h"
 
+#include "llagent.h"
 #include "llavataractions.h"
 #include "llavatariconctrl.h"
 #include "llbutton.h"
@@ -41,6 +42,53 @@
 #include "llavatarlist.h"
 #include "llparticipantlist.h"
 #include "llimview.h"
+#include "llvoicechannel.h"
+
+void LLPanelChatControlPanel::onCallButtonClicked()
+{
+	gIMMgr->startCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onEndCallButtonClicked()
+{
+	gIMMgr->endCall(mSessionId);
+}
+
+BOOL LLPanelChatControlPanel::postBuild()
+{
+	childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
+	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
+
+	return TRUE;
+}
+
+void LLPanelChatControlPanel::draw()
+{
+	// hide/show start call and end call buttons
+	bool voice_enabled = LLVoiceClient::voiceEnabled();
+
+	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
+	if (!session) return;
+
+	LLVoiceChannel* voice_channel = session->mVoiceChannel;
+	if (voice_channel && voice_enabled)
+	{
+		childSetVisible("end_call_btn", voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+		childSetVisible("call_btn", voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
+	}
+
+	bool session_initialized = session->mSessionInitialized;
+	bool callback_enabled = session->mCallBackEnabled;
+	LLViewerRegion* region = gAgent.getRegion();
+
+	BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "")
+		&& session_initialized
+		&& voice_enabled
+		&& callback_enabled;
+	childSetEnabled("call_btn", enable_connect);
+
+	LLPanel::draw();
+}
 
 LLPanelIMControlPanel::LLPanelIMControlPanel()
 {
@@ -54,11 +102,11 @@ BOOL LLPanelIMControlPanel::postBuild()
 {
 	childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this));
 	childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this));
-	childSetAction("call_btn", boost::bind(&LLPanelIMControlPanel::onCallButtonClicked, this));
+
 	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
 	childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
-
-	return TRUE;
+	
+	return LLPanelChatControlPanel::postBuild();
 }
 
 void LLPanelIMControlPanel::onViewProfileButtonClicked()
@@ -73,22 +121,29 @@ void LLPanelIMControlPanel::onAddFriendButtonClicked()
 	LLAvatarActions::requestFriendshipDialog(avatar_icon->getAvatarId(), full_name);
 }
 
-void LLPanelIMControlPanel::onCallButtonClicked()
-{
-	// *TODO: Implement
-}
-
 void LLPanelIMControlPanel::onShareButtonClicked()
 {
 	// *TODO: Implement
 }
 
-void LLPanelIMControlPanel::setID(const LLUUID& avatar_id)
+void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
 {
+	LLPanelChatControlPanel::setSessionId(session_id);
+
+	LLIMModel& im_model = LLIMModel::instance();
+
+	LLUUID avatar_id = im_model.getOtherParticipantID(session_id);
+
 	// Disable "Add friend" button for friends.
 	childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(avatar_id));
 
 	getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(avatar_id);
+
+	// Disable profile button if participant is not realy SL avatar
+	LLIMModel::LLIMSession* im_session =
+		im_model.findIMSession(session_id);
+	if( im_session && !im_session->mOtherParticipantIsAvatar )
+		childSetEnabled("view_profile_btn", FALSE);
 }
 
 
@@ -100,12 +155,11 @@ LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id)
 BOOL LLPanelGroupControlPanel::postBuild()
 {
 	childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this));
-	childSetAction("call_btn", boost::bind(&LLPanelGroupControlPanel::onCallButtonClicked, this));
 
 	mAvatarList = getChild<LLAvatarList>("speakers_list");
 	mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
 
-	return TRUE;
+	return LLPanelChatControlPanel::postBuild();
 }
 
 LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
@@ -127,13 +181,23 @@ void LLPanelGroupControlPanel::onGroupInfoButtonClicked()
 }
 
 
-void LLPanelGroupControlPanel::onCallButtonClicked()
+void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
 {
-	// *TODO: Implement
+	LLPanelChatControlPanel::setSessionId(session_id);
+
+	mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id);
 }
 
 
-void LLPanelGroupControlPanel::setID(const LLUUID& id)
+LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id)
+{
+}
+
+BOOL LLPanelAdHocControlPanel::postBuild()
 {
-	mGroupID = id;
+	mAvatarList = getChild<LLAvatarList>("speakers_list");
+	mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
+
+	return LLPanelChatControlPanel::postBuild();
 }
+
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 138b1630c454d59e983d3ba7aa9e7d20b381ee81..220b7b14ba66ba1c578967105ad0e36bb7156d64 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -45,8 +45,16 @@ class LLPanelChatControlPanel : public LLPanel
 	LLPanelChatControlPanel() {};
 	~LLPanelChatControlPanel() {};
 
-	// sets the group or avatar UUID
-	virtual void setID(const LLUUID& avatar_id)= 0;
+	virtual BOOL postBuild();
+	virtual void draw();
+
+	void onCallButtonClicked();
+	void onEndCallButtonClicked();
+
+	virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; }
+
+private:
+	LLUUID mSessionId;
 };
 
 
@@ -58,13 +66,14 @@ class LLPanelIMControlPanel : public LLPanelChatControlPanel
 
 	BOOL postBuild();
 
-	void setID(const LLUUID& avatar_id);
+	void setSessionId(const LLUUID& session_id);
 
 private:
 	void onViewProfileButtonClicked();
 	void onAddFriendButtonClicked();
-	void onCallButtonClicked();
 	void onShareButtonClicked();
+
+	LLUUID mAvatarID;
 };
 
 
@@ -76,19 +85,26 @@ class LLPanelGroupControlPanel : public LLPanelChatControlPanel
 
 	BOOL postBuild();
 
-	void setID(const LLUUID& id);
+	void setSessionId(const LLUUID& session_id);
 	/*virtual*/ void draw();
 
-private:
-	void onGroupInfoButtonClicked();
-	void onCallButtonClicked();
-
+protected:
 	LLUUID mGroupID;
 	LLSpeakerMgr* mSpeakerManager;
 	LLAvatarList* mAvatarList;
 	LLParticipantList* mParticipantList;
+
+private:
+	void onGroupInfoButtonClicked();
 };
 
+class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel
+{
+public:
+	LLPanelAdHocControlPanel(const LLUUID& session_id);
+
+	BOOL postBuild();
 
+};
 
 #endif // LL_LLPANELIMCONTROLPANEL_H
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 83fb147a4960e12b68269d308144374995b6bb28..3d0db7104531f745ee931c5e3019f9ba6bc88c2d 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -38,10 +38,12 @@
 #include "llsdutil.h"
 #include "llsdutil_math.h"
 
+#include "llaccordionctrl.h"
 #include "llaccordionctrltab.h"
 #include "llagent.h"
 #include "llagentpicksinfo.h"
 #include "llagentui.h"
+#include "llcallbacklist.h"
 #include "lldndbutton.h"
 #include "llfloaterworldmap.h"
 #include "llfolderviewitem.h"
@@ -56,7 +58,7 @@
 //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
 
 static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
-static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn";
+static const std::string ADD_BUTTON_NAME = "add_btn";
 static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
 static const std::string TRASH_BUTTON_NAME = "trash_btn";
 
@@ -75,6 +77,7 @@ LLLandmarksPanel::LLLandmarksPanel()
 	,	mListCommands(NULL)
 	,	mGearFolderMenu(NULL)
 	,	mGearLandmarkMenu(NULL)
+	,	mDirtyFilter(false)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
 }
@@ -98,16 +101,37 @@ BOOL LLLandmarksPanel::postBuild()
 	initMyInventroyPanel();
 	initLibraryInventroyPanel();
 
+	gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);
 	return TRUE;
 }
 
 // virtual
 void LLLandmarksPanel::onSearchEdit(const std::string& string)
 {
+	static std::string prev_string("");
+
+	if (prev_string == string) return;
+
+	// show all folders in Landmarks Accordion for empty filter
+	mLandmarksInventoryPanel->setShowFolderState(string.empty() ?
+		LLInventoryFilter::SHOW_ALL_FOLDERS :
+		LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
+		);
+
 	filter_list(mFavoritesInventoryPanel, string);
 	filter_list(mLandmarksInventoryPanel, string);
 	filter_list(mMyInventoryPanel, string);
 	filter_list(mLibraryInventoryPanel, string);
+
+	prev_string = string;
+	mDirtyFilter = true;
+
+	// give FolderView a chance to be refreshed. So, made all accordions visible
+	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+	{
+		LLAccordionCtrlTab* tab = *iter;
+		tab->setVisible(true);
+	}
 }
 
 // virtual
@@ -300,6 +324,8 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
 					panel_pick, panel_places,params));
 			panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
 				panel_pick, panel_places,params));
+			panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
+							panel_pick, panel_places,params));
 		}
 	}
 }
@@ -389,6 +415,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis
 void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
 {
 	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
+	mAccordionTabs.push_back(accordion_tab);
 	accordion_tab->setDropDownStateChangedCallback(
 		boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
 }
@@ -433,11 +460,11 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	mListCommands = getChild<LLPanel>("bottom_panel");
 
 	mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
-	mListCommands->childSetAction(ADD_LANDMARK_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddLandmarkButtonClick, this));
-	mListCommands->childSetAction(ADD_FOLDER_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddFolderButtonClick, this));
 	mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
+	mListCommands->getChild<LLButton>(ADD_BUTTON_NAME)->setHeldDownCallback(boost::bind(&LLLandmarksPanel::onAddButtonHeldDown, this));
+	static const LLSD add_landmark_command("add_landmark");
+	mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddAction, this, add_landmark_command));
 
-	
 	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
 	trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
 			,	_4 // BOOL drop
@@ -453,6 +480,7 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
 	mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 }
 
 
@@ -488,52 +516,26 @@ void LLLandmarksPanel::onActionsButtonClick()
 		mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
 		menu = mGearFolderMenu;
 	}
-	if(menu)
-	{
-		menu->buildDrawLabels();
-		menu->updateParent(LLMenuGL::sMenuContainer);
-		LLView* actions_btn  = getChild<LLView>(OPTIONS_BUTTON_NAME);
-		S32 menu_x, menu_y;
-		actions_btn->localPointToOtherView(0,actions_btn->getRect().getHeight(),&menu_x,&menu_y, this);
-		menu_y += menu->getRect().getHeight();
-		LLMenuGL::showPopup(this, menu, menu_x,menu_y);
-	}
+	showActionMenu(menu,OPTIONS_BUTTON_NAME);
 }
 
-void LLLandmarksPanel::onAddLandmarkButtonClick() const
+void LLLandmarksPanel::onAddButtonHeldDown()
 {
-	if(LLLandmarkActions::landmarkAlreadyExists())
-	{
-		std::string location;
-		LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
-		llwarns<<" Landmark already exists at location:  "<< location<<llendl;
-		return;
-	}
-	LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
+	showActionMenu(mMenuAdd,ADD_BUTTON_NAME);
 }
 
-void LLLandmarksPanel::onAddFolderButtonClick() const
+void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
 {
-	LLFolderViewItem*  item = getCurSelectedItem();
-	if(item &&  mCurrentSelectedList == mLandmarksInventoryPanel)
+	if (menu)
 	{
-		LLFolderViewEventListener* folder_bridge = NULL;
-		if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
-		{
-			// for a landmark get parent folder bridge
-			folder_bridge = item->getParentFolder()->getListener();
-		}
-		else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY) 
-		{
-			// for a folder get its own bridge
-			folder_bridge = item->getListener();
-		}
-
-		menu_create_inventory_item(mCurrentSelectedList->getRootFolder()
-			, dynamic_cast<LLFolderBridge*>(folder_bridge)
-			, LLSD("category")
-			, gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK)
-			);
+		menu->buildDrawLabels();
+		menu->updateParent(LLMenuGL::sMenuContainer);
+		LLView* spawning_view = getChild<LLView> (spawning_view_name);
+		S32 menu_x, menu_y;
+		//show menu in co-ordinates of panel
+		spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+		menu_y += menu->getRect().getHeight();
+		LLMenuGL::showPopup(this, menu, menu_x, menu_y);
 	}
 }
 
@@ -547,11 +549,39 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 	std::string command_name = userdata.asString();
 	if("add_landmark" == command_name)
 	{
-		onAddLandmarkButtonClick();
+		if(LLLandmarkActions::landmarkAlreadyExists())
+		{
+			std::string location;
+			LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
+			llwarns<<" Landmark already exists at location:  "<< location<<llendl;
+			return;
+		}
+		LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
 	} 
 	else if ("category" == command_name)
 	{
-		onAddFolderButtonClick();
+		LLFolderViewItem* item = getCurSelectedItem();
+		if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
+		{
+			LLFolderViewEventListener* folder_bridge = NULL;
+			if (item-> getListener()->getInventoryType()
+					== LLInventoryType::IT_LANDMARK)
+			{
+				// for a landmark get parent folder bridge
+				folder_bridge = item->getParentFolder()->getListener();
+			}
+			else if (item-> getListener()->getInventoryType()
+					== LLInventoryType::IT_CATEGORY)
+			{
+				// for a folder get its own bridge
+				folder_bridge = item->getListener();
+			}
+
+			menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),
+					dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(
+							"category"), gInventory.findCategoryUUIDForType(
+							LLAssetType::AT_LANDMARK));
+		}
 	}
 }
 
@@ -854,6 +884,43 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
 }
 
 
+void LLLandmarksPanel::doIdle(void* landmarks_panel)
+{
+	LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel;
+
+	if (panel->mDirtyFilter)
+	{
+		panel->updateFilteredAccordions();
+	}
+
+}
+
+void LLLandmarksPanel::updateFilteredAccordions()
+{
+	LLInventoryPanel* inventory_list = NULL;
+	LLAccordionCtrlTab* accordion_tab = NULL;
+	for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+	{
+		accordion_tab = *iter;
+		inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView());
+		if (NULL == inventory_list) continue;
+		LLFolderView* fv = inventory_list->getRootFolder();
+
+		bool has_visible_children = fv->hasVisibleChildren();
+
+		accordion_tab->setVisible(has_visible_children);
+	}
+
+	// we have to arrange accordion tabs for cases when filter string is less restrictive but 
+	// all items are still filtered.
+	static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+	accordion->arrange();
+
+	// now filter state is applied to accordion tabs
+	mDirtyFilter = false;
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 // HELPER FUNCTIONS
 //////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 47c9f7647cd311c4abe0c9f4d5d421cd8b38f4de..0e7abb486501fbccc224c0e1c2235701f83f938e 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -41,6 +41,7 @@
 #include "llpanelpick.h"
 #include "llremoteparcelrequest.h"
 
+class LLAccordionCtrlTab;
 class LLFolderViewItem;
 class LLMenuGL;
 class LLInventoryPanel;
@@ -90,8 +91,8 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	void initListCommandsHandlers();
 	void updateListCommands();
 	void onActionsButtonClick();
-	void onAddLandmarkButtonClick() const;
-	void onAddFolderButtonClick() const;
+	void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+	void onAddButtonHeldDown();
 	void onTrashButtonClick() const;
 	void onAddAction(const LLSD& command_name) const;
 	void onClipboardAction(const LLSD& command_name) const;
@@ -114,6 +115,18 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	 */
 	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
 
+	/**
+	 * Static callback for gIdleCallbacks to perform actions out of drawing
+	 */
+	static void doIdle(void* landmarks_panel);
+
+	/**
+	 * Updates accordions according to filtered items in lists.
+	 *
+	 * It hides accordion for empty lists
+	 */
+	void updateFilteredAccordions();
+
 private:
 	LLInventorySubTreePanel*	mFavoritesInventoryPanel;
 	LLInventorySubTreePanel*	mLandmarksInventoryPanel;
@@ -121,10 +134,15 @@ class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
 	LLInventorySubTreePanel*	mLibraryInventoryPanel;
 	LLMenuGL*					mGearLandmarkMenu;
 	LLMenuGL*					mGearFolderMenu;
+	LLMenuGL*					mMenuAdd;
 	LLInventorySubTreePanel*	mCurrentSelectedList;
 
 	LLPanel*					mListCommands;
 	bool 						mSortByDate;
+	bool						mDirtyFilter;
+	
+	typedef	std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
+	accordion_tabs_t			mAccordionTabs;
 };
 
 #endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 61d66873ea564d7f36d5cc8c3ec68e6e42a5595d..4580eeb336af3591db99b8d0f7da2020ded7e0dd 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -413,13 +413,17 @@ BOOL LLPanelPeople::postBuild()
 	mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online");
 	mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");
 	mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
+	mOnlineFriendList->setShowIcons("FriendsListShowIcons");
 	mAllFriendList->setNoItemsCommentText(getString("no_friends"));
+	mAllFriendList->setShowIcons("FriendsListShowIcons");
 
 	mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
 	mNearbyList->setNoItemsCommentText(getString("no_one_near"));
+	mNearbyList->setShowIcons("NearbyListShowIcons");
 
 	mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
 	mRecentList->setNoItemsCommentText(getString("no_people"));
+	mRecentList->setShowIcons("RecentListShowIcons");
 
 	mGroupList = getChild<LLGroupList>("group_list");
 	mGroupList->setNoItemsCommentText(getString("no_groups"));
@@ -611,6 +615,10 @@ void LLPanelPeople::updateButtons()
 	bool recent_tab_active	= (cur_tab == RECENT_TAB_NAME);
 	LLUUID selected_id;
 
+	std::vector<LLUUID> selected_uuids;
+	getCurrentItemIDs(selected_uuids);
+	bool item_selected = (selected_uuids.size() == 1);
+
 	buttonSetVisible("group_info_btn",		group_tab_active);
 	buttonSetVisible("chat_btn",			group_tab_active);
 	buttonSetVisible("add_friend_btn",		nearby_tab_active || recent_tab_active);
@@ -621,7 +629,6 @@ void LLPanelPeople::updateButtons()
 
 	if (group_tab_active)
 	{
-		bool item_selected = mGroupList->getSelectedItem() != NULL;
 		bool cur_group_active = true;
 
 		if (item_selected)
@@ -629,7 +636,7 @@ void LLPanelPeople::updateButtons()
 			selected_id = mGroupList->getSelectedUUID();
 			cur_group_active = (gAgent.getGroupID() == selected_id);
 		}
-	
+
 		LLPanel* groups_panel = mTabContainer->getCurrentPanel();
 		groups_panel->childSetEnabled("activate_btn",	item_selected && !cur_group_active); // "none" or a non-active group selected
 		groups_panel->childSetEnabled("plus_btn",		item_selected);
@@ -640,18 +647,18 @@ void LLPanelPeople::updateButtons()
 		bool is_friend = true;
 
 		// Check whether selected avatar is our friend.
-		if ((selected_id = getCurrentItemID()).notNull())
+		if (item_selected)
 		{
+			selected_id = selected_uuids.front();
 			is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL;
 		}
 
 		childSetEnabled("add_friend_btn",	!is_friend);
 	}
 
-	bool item_selected = selected_id.notNull();
 	buttonSetEnabled("teleport_btn",		friends_tab_active && item_selected);
 	buttonSetEnabled("view_profile_btn",	item_selected);
-	buttonSetEnabled("im_btn",				item_selected);
+	buttonSetEnabled("im_btn",				(selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection
 	buttonSetEnabled("call_btn",			item_selected && false); // not implemented yet
 	buttonSetEnabled("share_btn",			item_selected && false); // not implemented yet
 	buttonSetEnabled("group_info_btn",		item_selected);
@@ -877,7 +884,17 @@ void LLPanelPeople::onAddFriendWizButtonClicked()
 
 void LLPanelPeople::onDeleteFriendButtonClicked()
 {
-	LLAvatarActions::removeFriendDialog(getCurrentItemID());
+	std::vector<LLUUID> selected_uuids;
+	getCurrentItemIDs(selected_uuids);
+
+	if (selected_uuids.size() == 1)
+	{
+		LLAvatarActions::removeFriendDialog( selected_uuids.front() );
+	}
+	else if (selected_uuids.size() > 1)
+	{
+		LLAvatarActions::removeFriendsDialog( selected_uuids );
+	}
 }
 
 void LLPanelPeople::onGroupInfoButtonClicked()
@@ -963,6 +980,8 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
 	}
 	else if (chosen_item == "view_icons")
 	{
+		mAllFriendList->toggleIcons();
+		mOnlineFriendList->toggleIcons();
 	}
 	else if (chosen_item == "organize_offline")
 	{
@@ -992,6 +1011,7 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
 	}
 	else if (chosen_item == "view_icons")
 	{
+		mNearbyList->toggleIcons();
 	}
 	else if (chosen_item == "sort_distance")
 	{
@@ -1011,7 +1031,7 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
 	}
 	else if (chosen_item == "view_icons")
 	{
-		// *TODO: implement showing/hiding icons
+		mRecentList->toggleIcons();
 	}
 }
 
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index cb9f7184f01dfad38ec6cd321249b96c2d4b53e6..5af27a5ec1cef8ab31b8e7def42872245261f2c9 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -55,6 +55,8 @@
 #include "llagent.h"
 #include "llagentui.h"
 #include "llavatarpropertiesprocessor.h"
+#include "llcallbacklist.h"
+#include "llexpandabletextbox.h"
 #include "llfloaterworldmap.h"
 #include "llfloaterbuycurrency.h"
 #include "llinventorymodel.h"
@@ -65,6 +67,7 @@
 #include "llviewerinventory.h"
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
+#include "llviewercontrol.h" 
 #include "llviewertexteditor.h"
 #include "llworldmap.h"
 #include "llsdutil_math.h"
@@ -76,7 +79,6 @@
 typedef std::pair<LLUUID, std::string> folder_pair_t;
 
 static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
 static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
 
 static LLRegisterPanelClassWrapper<LLPanelPlaceInfo> t_place_info("panel_place_info");
@@ -111,7 +113,7 @@ BOOL LLPanelPlaceInfo::postBuild()
 
 	mForSalePanel = getChild<LLPanel>("for_sale_panel");
 	mYouAreHerePanel = getChild<LLPanel>("here_panel");
-	LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLPanelPlaceInfo::updateYouAreHereBanner,this));
+	gIdleCallbacks.addFunction(&LLPanelPlaceInfo::updateYouAreHereBanner, this);
 	
 	//Icon value should contain sale price of last selected parcel. 
 	mForSalePanel->getChild<LLIconCtrl>("icon_for_sale")->
@@ -120,7 +122,7 @@ BOOL LLPanelPlaceInfo::postBuild()
 	mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
 	mRegionName = getChild<LLTextBox>("region_title");
 	mParcelName = getChild<LLTextBox>("parcel_title");
-	mDescEditor = getChild<LLTextEditor>("description");
+	mDescEditor = getChild<LLExpandableTextBox>("description");
 
 	mMaturityRatingText = getChild<LLTextBox>("maturity_value");
 	mParcelOwner = getChild<LLTextBox>("owner_value");
@@ -456,13 +458,13 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
 		mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
 	}
 
-	if(!parcel_data.name.empty())
+	if(!parcel_data.sim_name.empty())
 	{
-		mParcelName->setText(parcel_data.name);
+		mRegionName->setText(parcel_data.sim_name);
 	}
 	else
 	{
-		mParcelName->setText(LLStringUtil::null);
+		mRegionName->setText(LLStringUtil::null);
 	}
 
 	if(!parcel_data.desc.empty())
@@ -509,19 +511,22 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
 		region_z = llround(mPosRegion.mV[VZ]);
 	}
 
-	std::string name = getString("not_available");
-	if (!parcel_data.sim_name.empty())
+	if (!parcel_data.name.empty())
 	{
-		name = llformat("%s (%d, %d, %d)",
-						parcel_data.sim_name.c_str(), region_x, region_y, region_z);
-		mRegionName->setText(name);
+		mParcelName->setText(llformat("%s (%d, %d, %d)",
+							 parcel_data.name.c_str(), region_x, region_y, region_z));
+	}
+	else
+	{
+		mParcelName->setText(getString("not_available"));
 	}
 
 	if (mInfoType == CREATE_LANDMARK)
 	{
 		if (parcel_data.name.empty())
 		{
-			mTitleEditor->setText(name);
+			mTitleEditor->setText(llformat("%s (%d, %d, %d)",
+								  parcel_data.sim_name.c_str(), region_x, region_y, region_z));
 		}
 		else
 		{
@@ -610,6 +615,9 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel,
 	parcel_data.name = parcel->getName();
 	parcel_data.sim_name = region->getName();
 	parcel_data.snapshot_id = parcel->getSnapshotID();
+	mPosRegion.setVec((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+					  (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+					  (F32)pos_global.mdV[VZ]);
 	parcel_data.global_x = pos_global.mdV[VX];
 	parcel_data.global_y = pos_global.mdV[VY];
 	parcel_data.global_z = pos_global.mdV[VZ];
@@ -986,18 +994,22 @@ void LLPanelPlaceInfo::populateFoldersList()
 		mFolderCombo->add(it->second, LLSD(it->first));
 }
 
-void LLPanelPlaceInfo::updateYouAreHereBanner()
+//static
+void LLPanelPlaceInfo::updateYouAreHereBanner(void* userdata)
 {
 	//YouAreHere Banner should be displayed only for selected places, 
 	// If you want to display it for landmark or teleport history item, you should check by mParcelId
 	
-	bool is_you_are_here = false;
-	if (mSelectedParcelID != S32(-1) && !mLastSelectedRegionID.isNull())
-	{
-		is_you_are_here = gAgent.getRegion()->getRegionID()== mLastSelectedRegionID &&
-		mSelectedParcelID == LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
-	}
-	mYouAreHerePanel->setVisible(is_you_are_here);
+	LLPanelPlaceInfo* self  = static_cast<LLPanelPlaceInfo*>(userdata);
+	if(!self->getVisible())
+		return;
+
+	static F32 radius  = gSavedSettings.getF32("YouAreHereDistance");
+
+	BOOL display_banner = self->mLastSelectedRegionID == gAgent.getRegion()->getRegionID() && 
+			LLAgentUI::checkAgentDistance(self->mPosRegion, radius);
+
+	self->mYouAreHerePanel->setVisible(display_banner);
 }
 
 void LLPanelPlaceInfo::onForSaleBannerClick()
@@ -1028,14 +1040,9 @@ void LLPanelPlaceInfo::onForSaleBannerClick()
 	
 	
 }
- 
-
-static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
-{
-	return left.second < right.second;
-}
 
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
+/*static*/
+std::string LLPanelPlaceInfo::getFullFolderName(const LLViewerInventoryCategory* cat)
 {
 	std::string name = cat->getName();
 	LLUUID parent_id;
@@ -1057,6 +1064,11 @@ static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
 	return name;
 }
 
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
+{
+	return left.second < right.second;
+}
+
 static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
 {
 	LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 7b3a8f050b98abde66539db5674e59930aac0b69..07a2434d59f598ded18f1baf63ae50cd3accbe06 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -43,6 +43,7 @@
 
 class LLButton;
 class LLComboBox;
+class LLExpandableTextBox;
 class LLInventoryItem;
 class LLLineEditor;
 class LLPanelPickEdit;
@@ -52,6 +53,7 @@ class LLTextBox;
 class LLTextEditor;
 class LLTextureCtrl;
 class LLViewerRegion;
+class LLViewerInventoryCategory;
 
 class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 {
@@ -131,11 +133,13 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
+	
+	 static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
 
 private:
 
 	void populateFoldersList();
-	void updateYouAreHereBanner();
+	static void updateYouAreHereBanner(void*);// added to gIdleCallbacks
 	void onForSaleBannerClick();
 
 	/**
@@ -161,7 +165,7 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
 	LLTextureCtrl*		mSnapshotCtrl;
 	LLTextBox*			mRegionName;
 	LLTextBox*			mParcelName;
-	LLTextEditor*		mDescEditor;
+	LLExpandableTextBox*mDescEditor;
 	LLTextBox*			mMaturityRatingText;
 	LLTextBox*			mParcelOwner;
 	LLTextBox*			mLastVisited;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 5ab823b6e53a49c77c54ada2c14cf33b091b562a..b2e9110e966311e287f2a29fea78bfbbb0de1efc 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -351,7 +351,16 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
 
 	if (is_landmark_editable)
 	{
-		mPlaceInfo->setLandmarkFolder(mItem->getParentUUID());
+		if(!mPlaceInfo->setLandmarkFolder(mItem->getParentUUID()) && !mItem->getParentUUID().isNull())
+		{
+			const LLViewerInventoryCategory* cat = gInventory.getCategory(mItem->getParentUUID());
+			if(cat)
+			{
+				std::string cat_fullname = LLPanelPlaceInfo::getFullFolderName(cat);
+				LLComboBox* folderList = mPlaceInfo->getChild<LLComboBox>("folder_combo");
+				folderList->add(cat_fullname, cat->getUUID(),ADD_TOP);
+			}
+		}
 	}
 
 	mPlaceInfo->displayItemInfo(mItem);
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ca7ebb1ad8cb19788e43ba83d1f87f647fefc9ac
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -0,0 +1,1095 @@
+/** 
+ * @file llpanelprimmediacontrols.cpp
+ * @brief media controls popup panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ * 
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+//LLPanelPrimMediaControls
+#include "llagent.h"
+#include "llparcel.h"
+#include "llpanel.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llrender.h"
+#include "lldrawable.h"
+#include "llviewerwindow.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llface.h"
+#include "llcombobox.h"
+#include "llslider.h"
+#include "llhudview.h"
+#include "lliconctrl.h"
+#include "lltoolpie.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llpanelprimmediacontrols.h"
+#include "llpluginclassmedia.h"
+#include "llprogressbar.h"
+#include "llviewercontrol.h"
+#include "llviewerparcelmgr.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llvovolume.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+glh::matrix4f glh_get_current_modelview();
+glh::matrix4f glh_get_current_projection();
+
+const F32 ZOOM_NEAR_PADDING		= 1.0f;
+const F32 ZOOM_MEDIUM_PADDING	= 1.15f;
+const F32 ZOOM_FAR_PADDING		= 1.5f;
+
+// Warning: make sure these two match!
+const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM };
+const int LLPanelPrimMediaControls::kNumZoomLevels = 2;
+
+//
+// LLPanelPrimMediaControls
+//
+
+LLPanelPrimMediaControls::LLPanelPrimMediaControls() : 
+	mAlpha(1.f),
+	mCurrentURL(""),
+	mPreviousURL(""),
+	mPauseFadeout(false),
+	mUpdateSlider(true),
+	mClearFaceOnFade(false),
+	mCurrentRate(0.0),
+	mMovieDuration(0.0),
+	mUpdatePercent(0)
+{
+	mCommitCallbackRegistrar.add("MediaCtrl.Close",		boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Back",		boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Forward",	boost::bind(&LLPanelPrimMediaControls::onClickForward, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Home",		boost::bind(&LLPanelPrimMediaControls::onClickHome, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Stop",		boost::bind(&LLPanelPrimMediaControls::onClickStop, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Reload",	boost::bind(&LLPanelPrimMediaControls::onClickReload, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Play",		boost::bind(&LLPanelPrimMediaControls::onClickPlay, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Pause",		boost::bind(&LLPanelPrimMediaControls::onClickPause, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Open",		boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.Zoom",		boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.CommitURL",	boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress",		boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown",	boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
+	mCommitCallbackRegistrar.add("MediaCtrl.ToggleMute",		boost::bind(&LLPanelPrimMediaControls::onToggleMute, this));
+	
+	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_prim_media_controls.xml");
+	mInactivityTimer.reset();
+	mFadeTimer.stop();
+	mCurrentZoom = ZOOM_NONE;
+	mScrollState = SCROLL_NONE;
+
+	mPanelHandle.bind(this);
+}
+LLPanelPrimMediaControls::~LLPanelPrimMediaControls()
+{
+}
+
+BOOL LLPanelPrimMediaControls::postBuild()
+{
+	LLButton* scroll_up_ctrl = getChild<LLButton>("scrollup");
+	scroll_up_ctrl->setClickedCallback(onScrollUp, this);
+	scroll_up_ctrl->setHeldDownCallback(onScrollUpHeld, this);
+	scroll_up_ctrl->setMouseUpCallback(onScrollStop, this);
+	LLButton* scroll_left_ctrl = getChild<LLButton>("scrollleft");
+	scroll_left_ctrl->setClickedCallback(onScrollLeft, this);
+	scroll_left_ctrl->setHeldDownCallback(onScrollLeftHeld, this);
+	scroll_left_ctrl->setMouseUpCallback(onScrollStop, this);
+	LLButton* scroll_right_ctrl = getChild<LLButton>("scrollright");
+	scroll_right_ctrl->setClickedCallback(onScrollRight, this);
+	scroll_right_ctrl->setHeldDownCallback(onScrollLeftHeld, this);
+	scroll_right_ctrl->setMouseUpCallback(onScrollStop, this);
+	LLButton* scroll_down_ctrl = getChild<LLButton>("scrolldown");
+	scroll_down_ctrl->setClickedCallback(onScrollDown, this);
+	scroll_down_ctrl->setHeldDownCallback(onScrollDownHeld, this);
+	scroll_down_ctrl->setMouseUpCallback(onScrollStop, this);
+	
+	LLUICtrl* media_address	= getChild<LLUICtrl>("media_address");
+	media_address->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+	mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");
+	mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
+
+	mCurrentZoom = ZOOM_NONE;
+	// clicks on HUD buttons do not remove keyboard focus from media
+	setIsChrome(TRUE);
+	return TRUE;
+}
+
+void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+	if (media_impl.notNull() && objectp.notNull())
+	{
+		mTargetImplID = media_impl->getMediaTextureID();
+		mTargetObjectID = objectp->getID();
+		mTargetObjectFace = face;
+		mTargetObjectNormal = pick_normal;
+		mClearFaceOnFade = false;
+	}
+	else
+	{
+		// This happens on a timer now.
+//		mTargetImplID = LLUUID::null;
+//		mTargetObjectID = LLUUID::null;
+//		mTargetObjectFace = 0;
+		mClearFaceOnFade = true;
+	}
+
+	updateShape();
+}
+
+void LLPanelPrimMediaControls::focusOnTarget()
+{
+	// Sets the media focus to the current target of the LLPanelPrimMediaControls.
+	// This is how we transition from hover to focus when the user clicks on a control.
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if(media_impl)
+	{
+		if(!media_impl->hasFocus())
+		{	
+			// The current target doesn't have media focus -- focus on it.
+			LLViewerObject* objectp = getTargetObject();
+			LLViewerMediaFocus::getInstance()->setFocusFace(objectp, mTargetObjectFace, media_impl, mTargetObjectNormal);
+		}
+	}	
+}
+
+LLViewerMediaImpl* LLPanelPrimMediaControls::getTargetMediaImpl()
+{
+	return LLViewerMedia::getMediaImplFromTextureID(mTargetImplID);
+}
+
+LLViewerObject* LLPanelPrimMediaControls::getTargetObject()
+{
+	return gObjectList.findObject(mTargetObjectID);
+}
+
+LLPluginClassMedia* LLPanelPrimMediaControls::getTargetMediaPlugin()
+{
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+	if(impl && impl->hasMedia())
+	{
+		return impl->getMediaPlugin();
+	}
+	
+	return NULL;
+}
+
+void LLPanelPrimMediaControls::updateShape()
+{
+	const S32 MIN_HUD_WIDTH=400;
+	const S32 MIN_HUD_HEIGHT=120;
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	LLViewerObject* objectp = getTargetObject();
+	
+	if(!media_impl)
+	{
+		setVisible(FALSE);
+		return;
+	}
+
+	LLPluginClassMedia* media_plugin = NULL;
+	if(media_impl->hasMedia())
+	{
+		media_plugin = media_impl->getMediaPlugin();
+	}
+	
+	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+	bool can_navigate = parcel->getMediaAllowNavigate();
+	bool enabled = false;
+	bool has_focus = media_impl->hasFocus();
+	setVisible(enabled);
+
+	if (objectp)
+	{
+		bool mini_controls = false;
+		LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
+		if (media_data && NULL != dynamic_cast<LLVOVolume*>(objectp))
+		{
+			// Don't show the media HUD if we do not have permissions
+			enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
+			mini_controls = (LLMediaEntry::MINI == media_data->getControls());
+		}
+		
+		//
+		// Set the state of the buttons
+		//
+		LLUICtrl* back_ctrl					= getChild<LLUICtrl>("back");
+		LLUICtrl* fwd_ctrl					= getChild<LLUICtrl>("fwd");
+		LLUICtrl* reload_ctrl				= getChild<LLUICtrl>("reload");
+		LLUICtrl* play_ctrl					= getChild<LLUICtrl>("play");
+		LLUICtrl* pause_ctrl				= getChild<LLUICtrl>("pause");
+		LLUICtrl* stop_ctrl					= getChild<LLUICtrl>("stop");
+		LLUICtrl* media_stop_ctrl			= getChild<LLUICtrl>("media_stop");
+		LLUICtrl* home_ctrl					= getChild<LLUICtrl>("home");
+		LLUICtrl* close_ctrl				= getChild<LLUICtrl>("close");
+		LLUICtrl* open_ctrl					= getChild<LLUICtrl>("new_window");
+        LLUICtrl* zoom_ctrl					= getChild<LLUICtrl>("zoom_frame");
+		LLPanel* media_loading_panel		= getChild<LLPanel>("media_progress_indicator");
+		LLUICtrl* media_address_ctrl		= getChild<LLUICtrl>("media_address");
+		LLUICtrl* media_play_slider_ctrl	= getChild<LLUICtrl>("media_play_position");
+		LLUICtrl* volume_ctrl				= getChild<LLUICtrl>("media_volume");
+		LLButton* volume_btn				= getChild<LLButton>("media_volume_button");
+		LLUICtrl* volume_up_ctrl			= getChild<LLUICtrl>("volume_up");
+		LLUICtrl* volume_down_ctrl			= getChild<LLUICtrl>("volume_down");
+		LLIconCtrl* whitelist_icon			= getChild<LLIconCtrl>("media_whitelist_flag");
+		LLIconCtrl* secure_lock_icon		= getChild<LLIconCtrl>("media_secure_lock_flag");
+		
+		LLUICtrl* media_panel_scroll		= getChild<LLUICtrl>("media_panel_scroll");
+		LLUICtrl* scroll_up_ctrl			= getChild<LLUICtrl>("scrollup");
+		LLUICtrl* scroll_left_ctrl			= getChild<LLUICtrl>("scrollleft");
+		LLUICtrl* scroll_right_ctrl			= getChild<LLUICtrl>("scrollright");
+		LLUICtrl* scroll_down_ctrl			= getChild<LLUICtrl>("scrolldown");		
+				
+		// XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,
+		// and that only the proper controls get made visible/enabled according to that mode. 
+		back_ctrl->setVisible(has_focus);
+		fwd_ctrl->setVisible(has_focus);
+		reload_ctrl->setVisible(has_focus);
+		stop_ctrl->setVisible(false);
+		home_ctrl->setVisible(has_focus);
+		close_ctrl->setVisible(has_focus);
+		open_ctrl->setVisible(true);
+		media_address_ctrl->setVisible(has_focus && !mini_controls);
+		media_play_slider_ctrl->setVisible(has_focus && !mini_controls);
+		volume_ctrl->setVisible(false);
+		volume_up_ctrl->setVisible(false);
+		volume_down_ctrl->setVisible(false);
+		
+		whitelist_icon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false);
+		// Disable zoom if HUD
+		zoom_ctrl->setEnabled(!objectp->isHUDAttachment());
+		secure_lock_icon->setVisible(false);
+		mCurrentURL = media_impl->getMediaURL();
+		
+		back_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
+		fwd_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate);
+		stop_ctrl->setEnabled(has_focus && can_navigate);
+		home_ctrl->setEnabled(has_focus && can_navigate);
+		LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE;
+
+		if(media_plugin && media_plugin->pluginSupportsMediaTime())
+		{
+			reload_ctrl->setEnabled(FALSE);
+			reload_ctrl->setVisible(FALSE);
+			media_stop_ctrl->setVisible(has_focus);
+			home_ctrl->setVisible(FALSE);
+			back_ctrl->setEnabled(has_focus);
+			fwd_ctrl->setEnabled(has_focus);
+			media_address_ctrl->setVisible(false);
+			media_address_ctrl->setEnabled(false);
+			media_play_slider_ctrl->setVisible(!mini_controls);
+			media_play_slider_ctrl->setEnabled(!mini_controls);
+				
+			volume_ctrl->setVisible(has_focus);
+			volume_up_ctrl->setVisible(has_focus);
+			volume_down_ctrl->setVisible(has_focus);
+			volume_ctrl->setEnabled(has_focus);
+
+			whitelist_icon->setVisible(false);
+			secure_lock_icon->setVisible(false);
+			scroll_up_ctrl->setVisible(false);
+			scroll_left_ctrl->setVisible(false);
+			scroll_right_ctrl->setVisible(false);
+			scroll_down_ctrl->setVisible(false);
+			media_panel_scroll->setVisible(false);
+				
+			F32 volume = media_impl->getVolume();
+			// movie's url changed
+			if(mCurrentURL!=mPreviousURL)
+			{
+				mMovieDuration = media_plugin->getDuration();
+				mPreviousURL = mCurrentURL;
+			}
+				
+			if(mMovieDuration == 0) 
+			{
+				mMovieDuration = media_plugin->getDuration();
+				media_play_slider_ctrl->setValue(0);
+				media_play_slider_ctrl->setEnabled(false);
+			}
+			// TODO: What if it's not fully loaded
+					
+			if(mUpdateSlider && mMovieDuration!= 0)
+			{
+				F64 current_time =  media_plugin->getCurrentTime();
+				F32 percent = current_time / mMovieDuration;
+				media_play_slider_ctrl->setValue(percent);
+				media_play_slider_ctrl->setEnabled(true);
+			}
+				
+			// video vloume
+			if(volume <= 0.0)
+			{
+				volume_up_ctrl->setEnabled(TRUE);
+				volume_down_ctrl->setEnabled(FALSE);
+				media_impl->setVolume(0.0);
+				volume_btn->setToggleState(true);
+			}
+			else if (volume >= 1.0)
+			{
+				volume_up_ctrl->setEnabled(FALSE);
+				volume_down_ctrl->setEnabled(TRUE);
+				media_impl->setVolume(1.0);
+				volume_btn->setToggleState(false);
+			}
+			else
+			{
+				volume_up_ctrl->setEnabled(TRUE);
+				volume_down_ctrl->setEnabled(TRUE);
+			}
+				
+			switch(result)
+			{
+				case LLPluginClassMediaOwner::MEDIA_PLAYING:
+					play_ctrl->setEnabled(FALSE);
+					play_ctrl->setVisible(FALSE);
+					pause_ctrl->setEnabled(TRUE);
+					pause_ctrl->setVisible(has_focus);
+					media_stop_ctrl->setEnabled(TRUE);
+					
+					break;
+				case LLPluginClassMediaOwner::MEDIA_PAUSED:
+				default:
+					pause_ctrl->setEnabled(FALSE);
+					pause_ctrl->setVisible(FALSE);
+					play_ctrl->setEnabled(TRUE);
+					play_ctrl->setVisible(has_focus);
+					media_stop_ctrl->setEnabled(FALSE);
+					break;
+			}
+		}
+		else   // web based
+		{
+			if(media_plugin)
+			{
+				mCurrentURL = media_plugin->getLocation();
+			}
+			else
+			{
+				mCurrentURL.clear();
+			}
+				
+			play_ctrl->setVisible(FALSE);
+			pause_ctrl->setVisible(FALSE);
+			media_stop_ctrl->setVisible(FALSE);
+			media_address_ctrl->setVisible(has_focus && !mini_controls);
+			media_address_ctrl->setEnabled(has_focus && !mini_controls);
+			media_play_slider_ctrl->setVisible(FALSE);
+			media_play_slider_ctrl->setEnabled(FALSE);
+				
+			volume_ctrl->setVisible(FALSE);
+			volume_up_ctrl->setVisible(FALSE);
+			volume_down_ctrl->setVisible(FALSE);
+			volume_ctrl->setEnabled(FALSE);
+			volume_up_ctrl->setEnabled(FALSE);
+			volume_down_ctrl->setEnabled(FALSE);
+				
+			scroll_up_ctrl->setVisible(has_focus);
+			scroll_left_ctrl->setVisible(has_focus);
+			scroll_right_ctrl->setVisible(has_focus);
+			scroll_down_ctrl->setVisible(has_focus);
+			media_panel_scroll->setVisible(has_focus);
+			// TODO: get the secure lock bool from media plug in
+			std::string prefix =  std::string("https://");
+			std::string test_prefix = mCurrentURL.substr(0, prefix.length());
+			LLStringUtil::toLower(test_prefix);
+			if(test_prefix == prefix)
+			{
+				secure_lock_icon->setVisible(has_focus);
+			}
+				
+			if(mCurrentURL!=mPreviousURL)
+			{
+				setCurrentURL();
+				mPreviousURL = mCurrentURL;
+			}
+
+			if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
+			{
+				reload_ctrl->setEnabled(FALSE);
+				reload_ctrl->setVisible(FALSE);
+				stop_ctrl->setEnabled(TRUE);
+				stop_ctrl->setVisible(has_focus);
+			}
+			else
+			{
+				reload_ctrl->setEnabled(TRUE);
+				reload_ctrl->setVisible(has_focus);
+				stop_ctrl->setEnabled(FALSE);
+				stop_ctrl->setVisible(FALSE);
+			}
+		}
+
+		
+		if(media_plugin)
+		{
+			//
+			// Handle progress bar
+			//
+			mUpdatePercent = media_plugin->getProgressPercent();
+			if(mUpdatePercent<100.0f)
+			{
+				media_loading_panel->setVisible(true);
+				getChild<LLProgressBar>("media_progress_bar")->setPercent(mUpdatePercent);
+				gFocusMgr.setTopCtrl(media_loading_panel);
+			}
+			else
+			{
+				media_loading_panel->setVisible(false);
+				gFocusMgr.setTopCtrl(NULL);
+			}
+		}
+
+		if(media_plugin)
+		{
+			//
+			// Handle Scrolling
+			//
+			switch (mScrollState) 
+			{
+			case SCROLL_UP:
+				media_plugin->scrollEvent(0, -1, MASK_NONE);
+				break;
+			case SCROLL_DOWN:
+				media_plugin->scrollEvent(0, 1, MASK_NONE);
+				break;
+			case SCROLL_LEFT:
+				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+				break;
+			case SCROLL_RIGHT:
+				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+				break;
+			case SCROLL_NONE:
+			default:
+				break;
+			}
+		}
+		
+		setVisible(enabled);
+
+		//
+		// Calculate position and shape of the controls
+		//
+		glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview();
+		std::vector<LLVector3>::iterator vert_it;
+		std::vector<LLVector3>::iterator vert_end;
+		std::vector<LLVector3> vect_face;
+
+		LLVolume* volume = objectp->getVolume();
+
+		if (volume)
+		{
+			const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
+
+			const LLVector3* ext = vf.mExtents;
+
+			LLVector3 center = (ext[0]+ext[1])*0.5f;
+			LLVector3 size = (ext[1]-ext[0])*0.5f;
+			LLVector3 vert[] =
+			{
+				center + size.scaledVec(LLVector3(1,1,1)),
+				center + size.scaledVec(LLVector3(-1,1,1)),
+				center + size.scaledVec(LLVector3(1,-1,1)),
+				center + size.scaledVec(LLVector3(-1,-1,1)),
+				center + size.scaledVec(LLVector3(1,1,-1)),
+				center + size.scaledVec(LLVector3(-1,1,-1)),
+				center + size.scaledVec(LLVector3(1,-1,-1)),
+				center + size.scaledVec(LLVector3(-1,-1,-1)),
+			};
+
+			LLVOVolume* vo = (LLVOVolume*) objectp;
+
+			for (U32 i = 0; i < 8; i++)
+			{
+				vect_face.push_back(vo->volumePositionToAgent(vert[i]));	
+			}
+		}
+		vert_it = vect_face.begin();
+		vert_end = vect_face.end();
+
+		LLVector3 min = LLVector3(1,1,1);
+		LLVector3 max = LLVector3(-1,-1,-1);
+		for(; vert_it != vert_end; ++vert_it)
+		{
+			// project silhouette vertices into screen space
+			glh::vec3f screen_vert = glh::vec3f(vert_it->mV); 
+			mat.mult_matrix_vec(screen_vert);
+
+			// add to screenspace bounding box
+			update_min_max(min, max, LLVector3(screen_vert.v));
+		}
+
+        LLCoordGL screen_min;
+		screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (min.mV[VX] + 1.f) * 0.5f);
+		screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (min.mV[VY] + 1.f) * 0.5f);
+
+		LLCoordGL screen_max;
+		screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (max.mV[VX] + 1.f) * 0.5f);
+		screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (max.mV[VY] + 1.f) * 0.5f);
+
+		// grow panel so that screenspace bounding box fits inside "media_region" element of HUD
+		LLRect media_controls_rect;
+		getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_controls_rect);
+		LLView* media_region = getChild<LLView>("media_region");
+		media_controls_rect.mLeft -= media_region->getRect().mLeft;
+		media_controls_rect.mBottom -= media_region->getRect().mBottom;
+		media_controls_rect.mTop += getRect().getHeight() - media_region->getRect().mTop;
+		media_controls_rect.mRight += getRect().getWidth() - media_region->getRect().mRight;
+
+		LLRect old_hud_rect = media_controls_rect;
+		// keep all parts of HUD on-screen
+		media_controls_rect.intersectWith(getParent()->getLocalRect());
+
+		// clamp to minimum size, keeping centered
+		media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(),
+			llmax(MIN_HUD_WIDTH, media_controls_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_controls_rect.getHeight()));
+
+		setShape(media_controls_rect, true);
+
+		// Test mouse position to see if the cursor is stationary
+		LLCoordWindow cursor_pos_window;
+		getWindow()->getCursorPosition(&cursor_pos_window);
+
+		// If last pos is not equal to current pos, the mouse has moved
+		// We need to reset the timer, and make sure the panel is visible
+		if(cursor_pos_window.mX != mLastCursorPos.mX ||
+			cursor_pos_window.mY != mLastCursorPos.mY ||
+			mScrollState != SCROLL_NONE)
+		{
+			mInactivityTimer.start();
+			mLastCursorPos = cursor_pos_window;
+		}
+		
+		if(isMouseOver())
+		{
+			// Never fade the controls if the mouse is over them.
+			mFadeTimer.stop();
+		}
+		else if(!mClearFaceOnFade && (mInactivityTimer.getElapsedTimeF32() < mInactiveTimeout))
+		{
+			// Mouse is over the object, but has not been stationary for long enough to fade the UI
+			mFadeTimer.stop();
+		}
+		else if(! mFadeTimer.getStarted() )
+		{
+			// we need to start fading the UI (and we have not already started)
+			mFadeTimer.reset();
+			mFadeTimer.start();
+		}
+		else
+		{
+			// I don't think this is correct anymore.  This is done in draw() after the fade has completed.
+//			setVisible(FALSE);
+		}
+	}
+}
+
+/*virtual*/
+void LLPanelPrimMediaControls::draw()
+{
+	F32 alpha = 1.f;
+	if(mFadeTimer.getStarted())
+	{
+		F32 time = mFadeTimer.getElapsedTimeF32();
+		alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
+
+		if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime)
+		{
+			setVisible(FALSE);
+			if(mClearFaceOnFade)
+			{
+				mClearFaceOnFade = false;
+				mTargetImplID = LLUUID::null;
+				mTargetObjectID = LLUUID::null;
+				mTargetObjectFace = 0;
+			}
+		}
+	}
+	
+	{
+		LLViewDrawContext context(alpha);
+		LLPanel::draw();
+	}
+}
+
+BOOL LLPanelPrimMediaControls::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+	mInactivityTimer.start();
+	return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	mInactivityTimer.start();
+	return LLPanel::handleMouseDown(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+	mInactivityTimer.start();
+	return LLPanel::handleMouseUp(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleKeyHere( KEY key, MASK mask )
+{
+	mInactivityTimer.start();
+	return LLPanel::handleKeyHere(key, mask);
+}
+
+bool LLPanelPrimMediaControls::isMouseOver()
+{
+	bool result = false;
+	
+	if( getVisible() )
+	{
+		LLCoordWindow cursor_pos_window;
+		LLCoordScreen cursor_pos_screen;
+		LLCoordGL cursor_pos_gl;
+		S32 x, y;
+		getWindow()->getCursorPosition(&cursor_pos_window);
+		getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+		
+		LLPanel* controls_panel = NULL;
+		controls_panel = getChild<LLPanel>("media_hover_controls");
+		if(controls_panel && !controls_panel->getVisible())
+		{
+			// The hover controls aren't visible -- use the focused controls instead.
+			controls_panel = getChild<LLPanel>("media_focused_controls");
+		}
+		
+		if(controls_panel && controls_panel->getVisible())
+		{
+			controls_panel->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y);
+
+			LLView *hit_child = controls_panel->childFromPoint(x, y);
+			if(hit_child)
+			{
+				// This was useful for debugging both coordinate translation and view hieararchy problems...
+//				llinfos << "mouse coords: " << x << ", " << y << " hit child " << hit_child->getName() << llendl;
+				result = true;
+			}
+		}
+	}
+
+	return result;
+}
+
+
+void LLPanelPrimMediaControls::onClickClose()
+{
+	close();
+}
+
+void LLPanelPrimMediaControls::close()
+{
+	LLViewerMediaFocus::getInstance()->clearFocus();
+	resetZoomLevel();
+	setVisible(FALSE);
+}
+
+
+void LLPanelPrimMediaControls::onClickBack()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl =getTargetMediaImpl();
+	
+	if (impl)
+	{
+		impl->navigateBack();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickForward()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+	
+	if (impl)
+	{
+		impl->navigateForward();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickHome()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->navigateHome();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickOpen()
+{
+	LLViewerMediaImpl* impl =getTargetMediaImpl();
+	if(impl)
+	{
+		if(impl->getMediaPlugin())
+		{	
+			if(impl->getMediaPlugin()->getLocation().empty())
+			{
+				LLWeb::loadURL(impl->getMediaURL());
+			}
+			else
+			{
+				LLWeb::loadURL( impl->getMediaPlugin()->getLocation());
+			}
+		}
+	}	
+}
+
+void LLPanelPrimMediaControls::onClickReload()
+{
+	focusOnTarget();
+
+	//LLViewerMedia::navigateHome();
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->navigateReload();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickPlay()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->play();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickPause()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->pause();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickStop()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->stop();
+	}
+}
+
+void LLPanelPrimMediaControls::onClickZoom()
+{
+	focusOnTarget();
+
+	nextZoomLevel();
+}
+void LLPanelPrimMediaControls::nextZoomLevel()
+{
+	int index = 0;
+	while (index < kNumZoomLevels)
+	{
+		if (kZoomLevels[index] == mCurrentZoom) 
+		{
+			index++;
+			break;
+		}
+		index++;
+	}
+	mCurrentZoom = kZoomLevels[index % kNumZoomLevels];
+	updateZoom();
+}
+
+void LLPanelPrimMediaControls::resetZoomLevel()
+{
+	if(mCurrentZoom != ZOOM_NONE)
+	{
+		mCurrentZoom = ZOOM_NONE;
+		updateZoom();
+	}
+}
+
+void LLPanelPrimMediaControls::updateZoom()
+{
+	F32 zoom_padding = 0.0f;
+	switch (mCurrentZoom)
+	{
+	case ZOOM_NONE:
+		{
+			gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+			break;
+		}
+	case ZOOM_FAR:
+		{
+			zoom_padding = ZOOM_FAR_PADDING;
+			break;
+		}
+	case ZOOM_MEDIUM:
+		{
+			zoom_padding = ZOOM_MEDIUM_PADDING;
+			break;
+		}
+	case ZOOM_NEAR:
+		{
+			zoom_padding = ZOOM_NEAR_PADDING;
+			break;
+		}
+	default:
+		{
+			gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+			break;
+		}
+	}
+
+	if (zoom_padding > 0.0f)		
+		LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding);
+}
+void LLPanelPrimMediaControls::onScrollUp(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLPluginClassMedia* plugin = this_panel->getTargetMediaPlugin();
+	
+	if(plugin)
+	{
+		plugin->scrollEvent(0, -1, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_UP;
+}
+void LLPanelPrimMediaControls::onScrollRight(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollRightHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_RIGHT;
+}
+
+void LLPanelPrimMediaControls::onScrollLeft(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+	if(impl)
+	{
+		impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollLeftHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_LEFT;
+}
+
+void LLPanelPrimMediaControls::onScrollDown(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->focusOnTarget();
+
+	LLPluginClassMedia* plugin = this_panel->getTargetMediaPlugin();
+	
+	if(plugin)
+	{
+		plugin->scrollEvent(0, 1, MASK_NONE);
+	}
+}
+void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_DOWN;
+}
+
+void LLPanelPrimMediaControls::onScrollStop(void* user_data)
+{
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+	this_panel->mScrollState = SCROLL_NONE;
+}
+
+void LLPanelPrimMediaControls::onCommitURL()
+{
+	focusOnTarget();
+
+	LLUICtrl *media_address_ctrl = getChild<LLUICtrl>("media_address_url");
+	std::string url = media_address_ctrl->getValue().asString();
+	if(getTargetMediaImpl() && !url.empty())
+	{
+		getTargetMediaImpl()->navigateTo( url, "", true);
+
+		// Make sure keyboard focus is set to the media focus object.
+		gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+			
+	}
+	mPauseFadeout = false;
+	mFadeTimer.start();
+}
+
+
+void LLPanelPrimMediaControls::onInputURL(LLFocusableElement* caller, void *userdata)
+{
+
+	LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (userdata);
+	this_panel->focusOnTarget();
+
+	this_panel->mPauseFadeout = true;
+	this_panel->mFadeTimer.stop();
+	this_panel->mFadeTimer.reset();
+	
+}
+
+void LLPanelPrimMediaControls::setCurrentURL()
+{	
+	LLComboBox* media_address_combo	= getChild<LLComboBox>("media_address_combo");
+	// redirects will navigate momentarily to about:blank, don't add to history
+	if (media_address_combo && mCurrentURL != "about:blank")
+	{
+		media_address_combo->remove(mCurrentURL);
+		media_address_combo->add(mCurrentURL, ADD_SORTED);
+		media_address_combo->selectByValue(mCurrentURL);
+	}
+}
+
+void LLPanelPrimMediaControls::onCommitSlider()
+{
+	focusOnTarget();
+
+	LLSlider* media_play_slider_ctrl	= getChild<LLSlider>("media_play_slider");
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		// get slider value
+		F64 slider_value = media_play_slider_ctrl->getValue().asReal();
+		if(slider_value <= 0.0)
+		{	
+			media_impl->stop();
+		}
+		else 
+		{
+			media_impl->seek(slider_value*mMovieDuration);
+			//mUpdateSlider= false;
+		}
+	}
+}		
+
+void LLPanelPrimMediaControls::onCommitVolumeUp()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		F32 volume = media_impl->getVolume();
+		
+		volume += 0.1f;
+		if(volume >= 1.0f)
+		{
+			volume = 1.0f;
+		}
+		
+		media_impl->setVolume(volume);
+		getChild<LLButton>("media_volume")->setToggleState(false);
+	}
+}		
+
+void LLPanelPrimMediaControls::onCommitVolumeDown()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		F32 volume = media_impl->getVolume();
+		
+		volume -= 0.1f;
+		if(volume <= 0.0f)
+		{
+			volume = 0.0f;
+		}
+
+		media_impl->setVolume(volume);
+		getChild<LLButton>("media_volume")->setToggleState(false);
+	}
+}		
+
+
+void LLPanelPrimMediaControls::onToggleMute()
+{
+	focusOnTarget();
+
+	LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+	if (media_impl) 
+	{
+		F32 volume = media_impl->getVolume();
+		
+		if(volume > 0.0)
+		{
+			media_impl->setVolume(0.0);
+		}
+		else 
+		{
+			media_impl->setVolume(0.5);
+		}
+	}
+}
+
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ec7aa2356c14614ce919050ba8b1b9da5970580
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -0,0 +1,148 @@
+/** 
+ * @file llpanelprimmediacontrols.h
+ * @brief Pop-up media controls panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ * 
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_PANELPRIMMEDIACONTROLS_H
+#define LL_PANELPRIMMEDIACONTROLS_H
+
+#include "llpanel.h"
+#include "llviewermedia.h"
+
+class LLCoordWindow;
+class LLViewerMediaImpl;
+
+class LLPanelPrimMediaControls : public LLPanel
+{
+public:
+	LLPanelPrimMediaControls();
+	virtual ~LLPanelPrimMediaControls();
+	/*virtual*/ BOOL postBuild();
+	virtual void draw();
+	virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+
+	virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+	virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL handleKeyHere(KEY key, MASK mask);
+	
+	void updateShape();
+	bool isMouseOver();
+	void nextZoomLevel();
+	void resetZoomLevel();
+	void close();
+
+	LLHandle<LLPanelPrimMediaControls>	getHandle() const { return mPanelHandle; }
+	void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+
+
+	enum EZoomLevel
+	{
+		ZOOM_NONE = 0,
+		ZOOM_FAR,
+		ZOOM_MEDIUM,
+		ZOOM_NEAR
+	};
+	static const EZoomLevel kZoomLevels[];
+	static const int kNumZoomLevels;
+	
+	enum EScrollDir
+	{
+		SCROLL_UP = 0,
+		SCROLL_DOWN,
+		SCROLL_LEFT,
+		SCROLL_RIGHT,
+		SCROLL_NONE
+	};
+
+private:
+	void onClickClose();
+	void onClickBack();
+	void onClickForward();
+	void onClickHome();
+	void onClickOpen();
+	void onClickReload();
+	void onClickPlay();
+	void onClickPause();
+	void onClickStop();
+	void onClickZoom();
+	void onCommitURL();
+	
+	void updateZoom();
+	void setCurrentURL();
+	void onCommitSlider();
+	
+	void onCommitVolumeUp();
+	void onCommitVolumeDown();
+	void onToggleMute();
+	
+	static void onScrollUp(void* user_data);
+	static void onScrollUpHeld(void* user_data);
+	static void onScrollLeft(void* user_data);
+	static void onScrollLeftHeld(void* user_data);
+	static void onScrollRight(void* user_data);
+	static void onScrollRightHeld(void* user_data);
+	static void onScrollDown(void* user_data);
+	static void onScrollDownHeld(void* user_data);
+	static void onScrollStop(void* user_data);
+	
+	static void onInputURL(LLFocusableElement* caller, void *userdata);
+	static bool hasControlsPermission(LLViewerObject *obj, const LLMediaEntry *media_entry);
+	
+	void focusOnTarget();
+	
+	LLViewerMediaImpl* getTargetMediaImpl();
+	LLViewerObject* getTargetObject();
+	LLPluginClassMedia* getTargetMediaPlugin();
+	bool mPauseFadeout;
+	bool mUpdateSlider;
+	bool mClearFaceOnFade;
+
+	LLMatrix4 mLastCameraMat;
+	EZoomLevel mCurrentZoom;
+	EScrollDir mScrollState;
+	LLCoordWindow mLastCursorPos;
+	LLFrameTimer mInactivityTimer;
+	LLFrameTimer mFadeTimer;
+	F32 mInactiveTimeout;
+	F32 mControlFadeTime;
+	LLRootHandle<LLPanelPrimMediaControls> mPanelHandle;
+	F32 mAlpha;
+	std::string mCurrentURL;
+	std::string mPreviousURL;
+	F64 mCurrentRate;
+	F64 mMovieDuration;
+	int mUpdatePercent;
+
+	LLUUID mTargetObjectID;
+	S32 mTargetObjectFace;
+	LLUUID mTargetImplID;
+	LLVector3 mTargetObjectNormal;
+};
+
+#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 25e773e8b8557ff590d75792eb46741269b5966d..e97eb1df2b66e8f1df7f4145e31f9c07acaf35bb 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -34,7 +34,7 @@
 
 #include "llparticipantlist.h"
 #include "llavatarlist.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
 
 //LLParticipantList retrieves add, clear and remove events and updates view accordingly 
 LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list):
@@ -48,6 +48,18 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
 	mSpeakerMgr->addListener(mSpeakerAddListener, "add");
 	mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
 	mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
+
+	//Lets fill avatarList with existing speakers
+	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+
+	LLSpeakerMgr::speaker_list_t speaker_list;
+	mSpeakerMgr->getSpeakerList(&speaker_list, true);
+	for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
+	{
+		group_members.push_back((*it)->mID);
+	}
+	mAvatarList->setDirty();
+	mAvatarList->sortByName();
 }
 
 LLParticipantList::~LLParticipantList()
@@ -87,8 +99,12 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L
 bool LLParticipantList::SpeakerRemoveListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
 {
 	LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
-	group_members.erase(std::find(group_members.begin(), group_members.end(), event->getValue().asUUID()));
-	mAvatarList->setDirty();
+	LLAvatarList::uuid_vector_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID());
+	if(pos != group_members.end())
+	{
+		group_members.erase(pos);
+		mAvatarList->setDirty();
+	}
 	return true;
 }
 
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 1683d113a997638c8fe89d9b7397933d52728639..73dcd1dd923aa8f6300390d1a654471f7f769f4c 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -191,19 +191,22 @@ void LLScreenChannel::onToastFade(LLToast* toast)
 {	
 	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
 		
-	bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
-	if(delete_toast)
-	{
-		mToastList.erase(it);
-		deleteToast(toast);
-	}
-	else
+	if(it != mToastList.end())
 	{
-		storeToast((*it));
-		mToastList.erase(it);
-	}	
+		bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
+		if(delete_toast)
+		{
+			mToastList.erase(it);
+			deleteToast(toast);
+		}
+		else
+		{
+			storeToast((*it));
+			mToastList.erase(it);
+		}	
 
-	redrawToasts();
+		redrawToasts();
+	}
 }
 
 //--------------------------------------------------------------------------
@@ -247,6 +250,7 @@ void LLScreenChannel::loadStoredToastsToChannel()
 
 	for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
 	{
+		(*it).toast->setIsHidden(false);
 		(*it).toast->resetTimer();
 		mToastList.push_back((*it));
 	}
@@ -266,6 +270,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
 	mOverflowToastHidden = false;
 
 	LLToast* toast = (*it).toast;
+	toast->setIsHidden(false);
 	toast->resetTimer();
 	mToastList.push_back((*it));
 	mStoredToastList.erase(it);
@@ -519,6 +524,7 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
 	LLRect toast_rect;
 	LLToast::Params p;
 	p.lifetime_secs = timer;
+	p.enable_hide_btn = false;
 	mStartUpToastPanel = new LLToast(p);
 
 	if(!mStartUpToastPanel)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2341fcfc6d64cc2be9d3f747f0df3a57ac0db457
--- /dev/null
+++ b/indra/newview/llspeakers.cpp
@@ -0,0 +1,639 @@
+/** 
+ * @file llspeakers.cpp
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llspeakers.h"
+
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llmutelist.h"
+#include "llsdutil.h"
+#include "lluicolortable.h"
+#include "llviewerobjectlist.h"
+#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);
+
+LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) : 
+	mStatus(LLSpeaker::STATUS_TEXT_ONLY),
+	mLastSpokeTime(0.f), 
+	mSpeechVolume(0.f), 
+	mHasSpoken(FALSE),
+	mHasLeftCurrentCall(FALSE),
+	mDotColor(LLColor4::white),
+	mID(id),
+	mTyping(FALSE),
+	mSortIndex(0),
+	mType(type),
+	mIsModerator(FALSE),
+	mModeratorMutedVoice(FALSE),
+	mModeratorMutedText(FALSE)
+{
+	if (name.empty() && type == SPEAKER_AGENT)
+	{
+		lookupName();
+	}
+	else
+	{
+		mDisplayName = name;
+	}
+
+	gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
+
+	mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+}
+
+
+void LLSpeaker::lookupName()
+{
+	gCacheName->get(mID, FALSE, boost::bind(&LLSpeaker::onAvatarNameLookup, this, _1, _2, _3, _4));
+}
+
+void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+{
+	mDisplayName = first + " " + last;
+}
+
+LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker text moderation event")
+{
+}
+
+LLSD LLSpeakerTextModerationEvent::getValue()
+{
+	return std::string("text");
+}
+
+
+LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker voice moderation event")
+{
+}
+
+LLSD LLSpeakerVoiceModerationEvent::getValue()
+{
+	return std::string("voice");
+}
+
+LLSpeakerListChangeEvent::LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id)
+: LLEvent(source, "Speaker added/removed from speaker mgr"),
+  mSpeakerID(speaker_id)
+{
+}
+
+LLSD LLSpeakerListChangeEvent::getValue()
+{
+	return mSpeakerID;
+}
+
+// helper sort class
+struct LLSortRecentSpeakers
+{
+	bool operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const;
+};
+
+bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const
+{
+	// Sort first on status
+	if (lhs->mStatus != rhs->mStatus) 
+	{
+		return (lhs->mStatus < rhs->mStatus);
+	}
+
+	// and then on last speaking time
+	if(lhs->mLastSpokeTime != rhs->mLastSpokeTime)
+	{
+		return (lhs->mLastSpokeTime > rhs->mLastSpokeTime);
+	}
+	
+	// and finally (only if those are both equal), on name.
+	return(	lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
+}
+
+
+//
+// LLSpeakerMgr
+//
+
+LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) : 
+	mVoiceChannel(channelp)
+{
+}
+
+LLSpeakerMgr::~LLSpeakerMgr()
+{
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
+{
+	if (id.isNull()) return NULL;
+
+	LLPointer<LLSpeaker> speakerp;
+	if (mSpeakers.find(id) == mSpeakers.end())
+	{
+		speakerp = new LLSpeaker(id, name, type);
+		speakerp->mStatus = status;
+		mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
+		mSpeakersSorted.push_back(speakerp);
+		fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
+	}
+	else
+	{
+		speakerp = findSpeaker(id);
+		if (speakerp.notNull())
+		{
+			// 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
+			if (type == LLSpeaker::SPEAKER_AGENT)
+			{
+				speakerp->mType = LLSpeaker::SPEAKER_AGENT;
+				speakerp->lookupName();
+			}
+		}
+	}
+
+	return speakerp;
+}
+
+void LLSpeakerMgr::update(BOOL resort_ok)
+{
+	if (!gVoiceClient)
+	{
+		return;
+	}
+	
+	LLColor4 speaking_color = LLUIColorTable::instance().getColor("SpeakingColor");
+	LLColor4 overdriven_color = LLUIColorTable::instance().getColor("OverdrivenColor");
+
+	if(resort_ok) // only allow list changes when user is not interacting with it
+	{
+		updateSpeakerList();
+	}
+
+	// update status of all current speakers
+	BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
+	{
+		LLUUID speaker_id = speaker_it->first;
+		LLSpeaker* speakerp = speaker_it->second;
+		
+		speaker_map_t::iterator  cur_speaker_it = speaker_it++;
+
+		if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
+		{
+			speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id);
+			BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id);
+			if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
+			{
+				speakerp->mModeratorMutedVoice = moderator_muted_voice;
+				speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
+			}
+
+			if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
+			{
+				speakerp->mStatus = LLSpeaker::STATUS_MUTED;
+			}
+			else if (gVoiceClient->getIsSpeaking(speaker_id))
+			{
+				// reset inactivity expiration
+				if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
+				{
+					speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+					speakerp->mHasSpoken = TRUE;
+				}
+				speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
+				// interpolate between active color and full speaking color based on power of speech output
+				speakerp->mDotColor = speaking_color;
+				if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
+				{
+					speakerp->mDotColor = overdriven_color;
+				}
+			}
+			else
+			{
+				speakerp->mSpeechVolume = 0.f;
+				speakerp->mDotColor = ACTIVE_COLOR;
+
+				if (speakerp->mHasSpoken)
+				{
+					// have spoken once, not currently speaking
+					speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN;
+				}
+				else
+				{
+					// default state for being in voice channel
+					speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE;
+				}
+			}
+		}
+		// speaker no longer registered in voice channel, demote to text only
+		else if (speakerp->mStatus != LLSpeaker::STATUS_NOT_IN_CHANNEL)
+		{
+			if(speakerp->mType == LLSpeaker::SPEAKER_EXTERNAL)
+			{
+				// external speakers should be timed out when they leave the voice channel (since they only exist via SLVoice)
+				speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+			}
+			else
+			{
+				speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY;
+				speakerp->mSpeechVolume = 0.f;
+				speakerp->mDotColor = ACTIVE_COLOR;
+			}
+		}
+	}
+
+	if(resort_ok)  // only allow list changes when user is not interacting with it
+	{
+		// sort by status then time last spoken
+		std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
+	}
+
+	// for recent speakers who are not currently speaking, show "recent" color dot for most recent
+	// fading to "active" color
+
+	S32 recent_speaker_count = 0;
+	S32 sort_index = 0;
+	speaker_list_t::iterator sorted_speaker_it;
+	for(sorted_speaker_it = mSpeakersSorted.begin(); 
+		sorted_speaker_it != mSpeakersSorted.end(); )
+	{
+		LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
+		
+		// color code recent speakers who are not currently speaking
+		if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
+		{
+			speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
+			recent_speaker_count++;
+		}
+
+		// 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;
+		}
+	}
+}
+
+void LLSpeakerMgr::updateSpeakerList()
+{
+	// are we bound to the currently active voice channel?
+	if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
+	{
+		LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList();
+		if(participants)
+		{
+			LLVoiceClient::participantMap::iterator participant_it;
+
+			// add new participants to our list of known speakers
+			for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it)
+			{
+				LLVoiceClient::participantState* participantp = participant_it->second;
+				setSpeaker(participantp->mAvatarID, participantp->mDisplayName, LLSpeaker::STATUS_VOICE_ACTIVE, (participantp->isAvatar()?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
+			}
+		}
+	}
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
+{
+	speaker_map_t::iterator found_it = mSpeakers.find(speaker_id);
+	if (found_it == mSpeakers.end())
+	{
+		return NULL;
+	}
+	return found_it->second;
+}
+
+void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text)
+{
+	speaker_list->clear();
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+	{
+		LLPointer<LLSpeaker> speakerp = speaker_it->second;
+		// what about text only muted or inactive?
+		if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY)
+		{
+			speaker_list->push_back(speakerp);
+		}
+	}
+}
+
+const LLUUID LLSpeakerMgr::getSessionID() 
+{ 
+	return mVoiceChannel->getSessionID(); 
+}
+
+
+void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing)
+{
+	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+	if (speakerp.notNull())
+	{
+		speakerp->mTyping = typing;
+	}
+}
+
+// speaker has chatted via either text or voice
+void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
+{
+	LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+	if (speakerp.notNull())
+	{
+		speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+		speakerp->mHasSpoken = TRUE;
+	}
+}
+
+BOOL LLSpeakerMgr::isVoiceActive()
+{
+	// mVoiceChannel = NULL means current voice channel, whatever it is
+	return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
+}
+
+
+//
+// LLIMSpeakerMgr
+//
+LLIMSpeakerMgr::LLIMSpeakerMgr(LLVoiceChannel* channel) : LLSpeakerMgr(channel)
+{
+}
+
+void LLIMSpeakerMgr::updateSpeakerList()
+{
+	// don't do normal updates which are pulled from voice channel
+	// rely on user list reported by sim
+	
+	// We need to do this to allow PSTN callers into group chats to show in the list.
+	LLSpeakerMgr::updateSpeakerList();
+	
+	return;
+}
+
+void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
+{
+	if ( !speakers.isMap() ) return;
+
+	if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
+	{
+		LLSD::map_const_iterator speaker_it;
+		for(speaker_it = speakers["agent_info"].beginMap();
+			speaker_it != speakers["agent_info"].endMap();
+			++speaker_it)
+		{
+			LLUUID agent_id(speaker_it->first);
+
+			LLPointer<LLSpeaker> speakerp = setSpeaker(
+				agent_id,
+				LLStringUtil::null,
+				LLSpeaker::STATUS_TEXT_ONLY);
+
+			if ( speaker_it->second.isMap() )
+			{
+				speakerp->mIsModerator = speaker_it->second["is_moderator"];
+				speakerp->mModeratorMutedText =
+					speaker_it->second["mutes"]["text"];
+			}
+		}
+	}
+	else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
+	{
+		//older, more decprecated way.  Need here for
+		//using older version of servers
+		LLSD::array_const_iterator speaker_it;
+		for(speaker_it = speakers["agents"].beginArray();
+			speaker_it != speakers["agents"].endArray();
+			++speaker_it)
+		{
+			const LLUUID agent_id = (*speaker_it).asUUID();
+
+			LLPointer<LLSpeaker> speakerp = setSpeaker(
+				agent_id,
+				LLStringUtil::null,
+				LLSpeaker::STATUS_TEXT_ONLY);
+		}
+	}
+}
+
+void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
+{
+	if ( !update.isMap() ) return;
+
+	if ( update.has("agent_updates") && update["agent_updates"].isMap() )
+	{
+		LLSD::map_const_iterator update_it;
+		for(
+			update_it = update["agent_updates"].beginMap();
+			update_it != update["agent_updates"].endMap();
+			++update_it)
+		{
+			LLUUID agent_id(update_it->first);
+			LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+			LLSD agent_data = update_it->second;
+
+			if (agent_data.isMap() && agent_data.has("transition"))
+			{
+				if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
+				{
+					speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+					speakerp->mDotColor = INACTIVE_COLOR;
+					speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+				}
+				else if (agent_data["transition"].asString() == "ENTER")
+				{
+					// add or update speaker
+					speakerp = setSpeaker(agent_id);
+				}
+				else
+				{
+					llwarns << "bad membership list update " << ll_print_sd(agent_data["transition"]) << llendl;
+				}
+			}
+
+			if (speakerp.isNull()) continue;
+
+			// should have a valid speaker from this point on
+			if (agent_data.isMap() && agent_data.has("info"))
+			{
+				LLSD agent_info = agent_data["info"];
+
+				if (agent_info.has("is_moderator"))
+				{
+					speakerp->mIsModerator = agent_info["is_moderator"];
+				}
+
+				if (agent_info.has("mutes"))
+				{
+					speakerp->mModeratorMutedText = agent_info["mutes"]["text"];
+				}
+			}
+		}
+	}
+	else if ( update.has("updates") && update["updates"].isMap() )
+	{
+		LLSD::map_const_iterator update_it;
+		for (
+			update_it = update["updates"].beginMap();
+			update_it != update["updates"].endMap();
+			++update_it)
+		{
+			LLUUID agent_id(update_it->first);
+			LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+			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);
+			}
+			else if ( agent_transition == "ENTER")
+			{
+				// add or update speaker
+				speakerp = setSpeaker(agent_id);
+			}
+			else
+			{
+				llwarns << "bad membership list update "
+						<< agent_transition << llendl;
+			}
+		}
+	}
+}
+
+
+//
+// LLActiveSpeakerMgr
+//
+
+LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL)
+{
+}
+
+void LLActiveSpeakerMgr::updateSpeakerList()
+{
+	// point to whatever the current voice channel is
+	mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+
+	// always populate from active voice channel
+	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
+	{
+		fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
+		mSpeakers.clear();
+		mSpeakersSorted.clear();
+		mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+	}
+	LLSpeakerMgr::updateSpeakerList();
+
+	// clean up text only speakers
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+	{
+		LLUUID speaker_id = speaker_it->first;
+		LLSpeaker* speakerp = speaker_it->second;
+		if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+		{
+			// automatically flag text only speakers for removal
+			speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+		}
+	}
+
+}
+
+
+
+//
+// LLLocalSpeakerMgr
+//
+
+LLLocalSpeakerMgr::LLLocalSpeakerMgr() : LLSpeakerMgr(LLVoiceChannelProximal::getInstance())
+{
+}
+
+LLLocalSpeakerMgr::~LLLocalSpeakerMgr ()
+{
+}
+
+void LLLocalSpeakerMgr::updateSpeakerList()
+{
+	// pull speakers from voice channel
+	LLSpeakerMgr::updateSpeakerList();
+
+	if (gDisconnected)//the world is cleared.
+	{
+		return ;
+	}
+
+	// pick up non-voice speakers in chat range
+	std::vector<LLUUID> avatar_ids;
+	std::vector<LLVector3d> positions;
+	LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
+	for(U32 i=0; i<avatar_ids.size(); i++)
+	{
+		setSpeaker(avatar_ids[i]);
+	}
+
+	// check if text only speakers have moved out of chat range
+	for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+	{
+		LLUUID speaker_id = speaker_it->first;
+		LLSpeaker* speakerp = speaker_it->second;
+		if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+		{
+			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);
+			}
+		}
+	}
+}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0f22bff4f421ba7f75dad8d595bcc19b6a02f4f
--- /dev/null
+++ b/indra/newview/llspeakers.h
@@ -0,0 +1,172 @@
+/** 
+ * @file llspeakers.h
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ * 
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSPEAKERS_H
+#define LL_LLSPEAKERS_H
+
+#include "llevent.h"
+#include "llspeakers.h"
+#include "llvoicechannel.h"
+
+class LLSpeakerMgr;
+
+// data for a given participant in a voice channel
+class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LLHandleProvider<LLSpeaker>, public boost::signals2::trackable
+{
+public:
+	typedef enum e_speaker_type
+	{
+		SPEAKER_AGENT,
+		SPEAKER_OBJECT,
+		SPEAKER_EXTERNAL	// Speaker that doesn't map to an avatar or object (i.e. PSTN caller in a group)
+	} ESpeakerType;
+
+	typedef enum e_speaker_status
+	{
+		STATUS_SPEAKING,
+		STATUS_HAS_SPOKEN,
+		STATUS_VOICE_ACTIVE,
+		STATUS_TEXT_ONLY,
+		STATUS_NOT_IN_CHANNEL,
+		STATUS_MUTED
+	} ESpeakerStatus;
+
+
+	LLSpeaker(const LLUUID& id, const std::string& name = LLStringUtil::null, const ESpeakerType type = SPEAKER_AGENT);
+	~LLSpeaker() {};
+	void lookupName();
+
+	void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+
+	ESpeakerStatus	mStatus;			// current activity status in speech group
+	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;
+	LLUUID			mID;
+	BOOL			mTyping;
+	S32				mSortIndex;
+	ESpeakerType	mType;
+	BOOL			mIsModerator;
+	BOOL			mModeratorMutedVoice;
+	BOOL			mModeratorMutedText;
+};
+
+class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+	LLSpeakerTextModerationEvent(LLSpeaker* source);
+	/*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerVoiceModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+	LLSpeakerVoiceModerationEvent(LLSpeaker* source);
+	/*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent
+{
+public:
+	LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id);
+	/*virtual*/ LLSD getValue();
+
+private:
+	const LLUUID& mSpeakerID;
+};
+
+class LLSpeakerMgr : public LLOldEvents::LLObservable
+{
+public:
+	LLSpeakerMgr(LLVoiceChannel* channelp);
+	virtual ~LLSpeakerMgr();
+
+	LLPointer<LLSpeaker> findSpeaker(const LLUUID& avatar_id);
+	void update(BOOL resort_ok);
+	void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
+	void speakerChatted(const LLUUID& speaker_id);
+	LLPointer<LLSpeaker> setSpeaker(const LLUUID& id, 
+					const std::string& name = LLStringUtil::null, 
+					LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY, 
+					LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT);
+
+	BOOL isVoiceActive();
+
+	typedef std::vector<LLPointer<LLSpeaker> > speaker_list_t;
+	void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text);
+	LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
+	const LLUUID getSessionID();
+
+protected:
+	virtual void updateSpeakerList();
+
+	typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
+	speaker_map_t		mSpeakers;
+
+	speaker_list_t		mSpeakersSorted;
+	LLFrameTimer		mSpeechTimer;
+	LLVoiceChannel*		mVoiceChannel;
+};
+
+class LLIMSpeakerMgr : public LLSpeakerMgr
+{
+public:
+	LLIMSpeakerMgr(LLVoiceChannel* channel);
+	
+	void updateSpeakers(const LLSD& update);
+	void setSpeakers(const LLSD& speakers);
+protected:
+	virtual void updateSpeakerList();
+};
+
+class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
+{
+public:
+	LLActiveSpeakerMgr();
+protected:
+	virtual void updateSpeakerList();
+};
+
+class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
+{
+public:
+	LLLocalSpeakerMgr();
+	~LLLocalSpeakerMgr ();
+protected:
+	virtual void updateSpeakerList();
+};
+
+#endif // LL_LLSPEAKERS_H
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 86290e66955a744f8f18552026cf04b21ee381a6..93a931dc788d973e1241ee29127ccc8eb54a7827 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -112,6 +112,12 @@ void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type)
 	}
 }
 
+//---------------------------------------------------------------------------------
+void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+	onChicletClick();
+}
+
 //---------------------------------------------------------------------------------
 void LLSysWellWindow::onChicletClick()
 {
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index fa6a1abea47ae7996b413e0229c6b545a752a5b5..cbc5f7358f0cf36e66b4cd7189ddb7d2ec6765f3 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -76,6 +76,7 @@ class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver
 	void onItemClose(LLSysWellItem* item);
 	void onStoreToast(LLPanel* info_panel, LLUUID id);
 	void onChicletClick();
+	void onStartUpToastClick(S32 x, S32 y, MASK mask);
 
 	// size constants for the window and for its elements
 	static const S32 MAX_WINDOW_HEIGHT		= 200;
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 17547cae39e115158005d14641ee17405f35548f..5d9046ac905c19af80d44ce21f2143d005218afe 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -804,8 +804,9 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
 	
 	gGL.setColorMask(false, true);
 	gGL.setSceneBlendType(LLRender::BT_REPLACE);
+	
 	// (Optionally) replace alpha with a single component image from a tga file.
-	if (!info->mStaticAlphaFileName.empty() && mMaskLayerList.empty())
+	if (!info->mStaticAlphaFileName.empty())
 	{
 		LLGLSNoAlphaTest gls_no_alpha_test;
 		gGL.flush();
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index eba43d76a6b1a999694d35e47d659e4778f24373..24824a095cb0d25e8f7e9a8dbda6a25d4d9423d8 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -63,6 +63,7 @@ LLToast::LLToast(const LLToast::Params& p)
 	mHideBtnEnabled(p.enable_hide_btn),
 	mHideBtn(NULL),
 	mNotification(p.notification),
+	mIsHidden(false),
 	mHideBtnPressed(false)
 {
 	LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL);
@@ -143,7 +144,8 @@ void LLToast::hide()
 {
 	setVisible(FALSE);
 	mTimer.stop();
-	mOnFadeSignal(this);
+	mIsHidden = true;
+	mOnFadeSignal(this); 
 }
 
 //--------------------------------------------------------------------------
@@ -159,9 +161,7 @@ void LLToast::tick()
 {
 	if(mCanFade)
 	{
-		setVisible(FALSE);
-		mTimer.stop();
-		mOnFadeSignal(this); 
+		hide();
 	}
 }
 
@@ -206,6 +206,16 @@ void LLToast::draw()
 //--------------------------------------------------------------------------
 void LLToast::setVisible(BOOL show)
 {
+	if(mIsHidden)
+	{
+		// this toast is invisible after fade until its ScreenChannel will allow it
+		//
+		// (EXT-1849) according to this bug a toast can be resurrected from
+		// invisible state if it faded during a teleportation
+		// then it fades a second time and causes a crash
+		return;
+	}
+
 	if(show)
 	{
 		setBackgroundOpaque(TRUE);
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 1826c13ebc8bc69185319151c2099336a0f66ea3..0698c9488022a945b0c93f04181ffa74f8adf7ff 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -125,6 +125,8 @@ class LLToast : public LLModalDialog
 	void setCanBeStored(bool can_be_stored) { mCanBeStored = can_be_stored; }
 	//
 	bool getCanBeStored() { return mCanBeStored; }
+	// set whether this toast considered as hidden or not
+	void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; }
 
 
 	// Registers signals/callbacks for events
@@ -164,6 +166,7 @@ class LLToast : public LLModalDialog
 	bool		mCanBeStored;
 	bool		mHideBtnEnabled;
 	bool		mHideBtnPressed;
+	bool		mIsHidden;  // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
 };
 
 }
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 57a4117d5d561a59f96dab90760b57b5cf21e77c..366e5602bd8696ab0b2e19134aca2193e08db8f9 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -42,7 +42,6 @@
 #include "llconsole.h"
 #include "llinventorymodel.h"
 #include "llnotify.h"
-#include "llimview.h"
 #include "llgesturemgr.h"
 
 #include "llinventorybridge.h"
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 02fda191bec9379775c332143e7ab92096a52c41..8bd74dcb04810e9a3df51fd797275dd53b8dc699 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -156,10 +156,10 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 	{
 		if(!mInitialized && ! mime_type.empty())
 		{
-			if (mMediaImpl->initializeMedia(mime_type))
+			if(mMediaImpl->initializeMedia(mime_type))
 			{
 				mInitialized = true;
-				mMediaImpl->play();
+				mMediaImpl->loadURI();
 			}
 		}
 	}
@@ -267,10 +267,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 			{
 				needs_navigate = (media_entry->getCurrentURL() != previous_url);
 			}
-			else if(!media_entry->getHomeURL().empty())
-			{
-				needs_navigate = (media_entry->getHomeURL() != previous_url);
-			}
 		}
 	}
 	else
@@ -293,8 +289,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 	if(media_impl && needs_navigate)
 	{
 		std::string url = media_entry->getCurrentURL();
-		if(url.empty())
-			url = media_entry->getHomeURL();
 			
 		media_impl->navigateTo(url, "", true, true);
 	}
@@ -639,13 +633,14 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mUsedInUI(false),
 	mHasFocus(false),
 	mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
-	mDoNavigateOnLoad(false),
-	mDoNavigateOnLoadRediscoverType(false),
-	mDoNavigateOnLoadServerRequest(false),
+	mNavigateRediscoverType(false),
+	mNavigateServerRequest(false),
 	mMediaSourceFailed(false),
 	mRequestedVolume(1.0f),
 	mIsMuted(false),
 	mNeedsMuteCheck(false),
+	mPreviousMediaState(MEDIA_NONE),
+	mPreviousMediaTime(0.0f),
 	mIsUpdated(false)
 { 
 
@@ -716,7 +711,6 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
 		mMimeType = mime_type;
 	}
 
-	// play();
 	return (mMediaSource != NULL);
 }
 
@@ -729,16 +723,13 @@ void LLViewerMediaImpl::createMediaSource()
 		return;
 	}
 	
-	if(mDoNavigateOnLoad)
+	if(! mMediaURL.empty())
 	{
-		if(! mMediaURL.empty())
-		{
-			navigateTo(mMediaURL, mMimeType, mDoNavigateOnLoadRediscoverType, mDoNavigateOnLoadServerRequest);
-		}
-		else if(! mMimeType.empty())
-		{
-			initializeMedia(mMimeType);
-		}
+		navigateInternal();
+	}
+	else if(! mMimeType.empty())
+	{
+		initializeMedia(mMimeType);
 	}
 }
 
@@ -869,6 +860,46 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
 	return false;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::loadURI()
+{
+	if(mMediaSource)
+	{
+		mMediaSource->loadURI( mMediaURL );
+
+		if(mPreviousMediaState == MEDIA_PLAYING)
+		{
+			// This media was playing before this instance was unloaded.
+
+			if(mPreviousMediaTime != 0.0f)
+			{
+				// Seek back to where we left off, if possible.
+				seek(mPreviousMediaTime);
+			}
+			
+			start();
+		}
+		else if(mPreviousMediaState == MEDIA_PAUSED)
+		{
+			// This media was paused before this instance was unloaded.
+
+			if(mPreviousMediaTime != 0.0f)
+			{
+				// Seek back to where we left off, if possible.
+				seek(mPreviousMediaTime);
+			}
+			
+			pause();
+		}
+		else
+		{
+			// No relevant previous media play state -- if we're loading the URL, we want to start playing.
+			start();
+		}
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::setSize(int width, int height)
 {
 	mMediaWidth = width;
@@ -882,24 +913,21 @@ void LLViewerMediaImpl::setSize(int width, int height)
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::play()
 {
-	// first stop any previously playing media
-	// stop();
-
-	// mMediaSource->addObserver( this );
+	// If the media source isn't there, try to initialize it and load an URL.
 	if(mMediaSource == NULL)
 	{
-	 	if(!initializePlugin(mMimeType))
+	 	if(!initializeMedia(mMimeType))
 		{
 			// This may be the case where the plugin's priority is PRIORITY_UNLOADED
 			return;
 		}
+		
+		// Only do this if the media source was just loaded.
+		loadURI();
 	}
 	
-	mMediaSource->loadURI( mMediaURL );
-	if(/*mMediaSource->pluginSupportsMediaTime()*/ true)
-	{
-		start();
-	}
+	// always start the media
+	start();
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1165,27 +1193,21 @@ void LLViewerMediaImpl::navigateHome()
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type,  bool rediscover_type, bool server_request)
 {
-	if(server_request)
-	{
-		setNavState(MEDIANAVSTATE_SERVER_SENT);
-	}
-	else
+	if(mMediaURL != url)
 	{
-		setNavState(MEDIANAVSTATE_NONE);
+		// Don't carry media play state across distinct URLs.
+		resetPreviousMediaState();
 	}
 	
 	// Always set the current URL and MIME type.
 	mMediaURL = url;
 	mMimeType = mime_type;
 	
-	// If the current URL is not null, make the instance do a navigate on load.
-	mDoNavigateOnLoad = !mMediaURL.empty();
-
 	// if mime type discovery was requested, we'll need to do it when the media loads
-	mDoNavigateOnLoadRediscoverType = rediscover_type;
+	mNavigateRediscoverType = rediscover_type;
 	
 	// and if this was a server request, the navigate on load will also need to be one.
-	mDoNavigateOnLoadServerRequest = server_request;
+	mNavigateServerRequest = server_request;
 	
 	// An explicit navigate resets the "failed" flag.
 	mMediaSourceFailed = false;
@@ -1193,7 +1215,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 	if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
 	{
 		// Helpful to have media urls in log file. Shouldn't be spammy.
-		llinfos << "UNLOADED media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
+		llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
 
 		// This impl should not be loaded at this time.
 		LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
@@ -1201,10 +1223,24 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 		return;
 	}
 
+	navigateInternal();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateInternal()
+{
 	// Helpful to have media urls in log file. Shouldn't be spammy.
-	llinfos << "media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
-	
-	
+	llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+
+	if(mNavigateServerRequest)
+	{
+		setNavState(MEDIANAVSTATE_SERVER_SENT);
+	}
+	else
+	{
+		setNavState(MEDIANAVSTATE_NONE);
+	}
+			
 	// If the caller has specified a non-empty MIME type, look that up in our MIME types list.
 	// If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
 	// This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
@@ -1216,11 +1252,11 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 		if(!plugin_basename.empty())
 		{
 			// We have a plugin for this mime type
-			rediscover_type = false;
+			mNavigateRediscoverType = false;
 		}
 	}
 
-	if(rediscover_type)
+	if(mNavigateRediscoverType)
 	{
 
 		LLURI uri(mMediaURL);
@@ -1236,7 +1272,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 			// We use "data" internally for a text/html url for loading the login screen
 			if(initializeMedia("text/html"))
 			{
-				mMediaSource->loadURI( mMediaURL );
+				loadURI();
 			}
 		}
 		else
@@ -1244,24 +1280,18 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
 			// This catches 'rtsp://' urls
 			if(initializeMedia(scheme))
 			{
-				mMediaSource->loadURI( mMediaURL );
+				loadURI();
 			}
 		}
 	}
-	else if (mMediaSource)
+	else if(initializeMedia(mMimeType))
 	{
-		mMediaSource->loadURI( mMediaURL );
-	}
-	else if(initializeMedia(mime_type) && mMediaSource)
-	{
-		mMediaSource->loadURI( mMediaURL );
+		loadURI();
 	}
 	else
 	{
-		LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL;
-		return;
+		LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
 	}
-
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1390,6 +1420,7 @@ void LLViewerMediaImpl::update()
 	
 	if(mMediaSource->isPluginExited())
 	{
+		resetPreviousMediaState();
 		destroyMediaSource();
 		return;
 	}
@@ -1585,6 +1616,14 @@ bool LLViewerMediaImpl::hasMedia()
 	return mMediaSource != NULL;
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+	mPreviousMediaState = MEDIA_NONE;
+	mPreviousMediaTime = 0.0f;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
 {
@@ -1595,6 +1634,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 			// The plugin failed to load properly.  Make sure the timer doesn't retry.
 			// TODO: maybe mark this plugin as not loadable somehow?
 			mMediaSourceFailed = true;
+
+			// Reset the last known state of the media to defaults.
+			resetPreviousMediaState();
 			
 			// TODO: may want a different message for this case?
 			LLSD args;
@@ -1608,6 +1650,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
 			// The plugin crashed.
 			mMediaSourceFailed = true;
 
+			// Reset the last known state of the media to defaults.
+			resetPreviousMediaState();
+
 			LLSD args;
 			args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
 			// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
@@ -1833,11 +1878,11 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
 	{
 		if(getVisible())
 		{
-			mPriority = LLPluginClassMedia::PRIORITY_NORMAL;
+			setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
 		}
 		else
 		{
-			mPriority = LLPluginClassMedia::PRIORITY_HIDDEN;
+			setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
 		}
 
 		createMediaSource();
@@ -1858,6 +1903,15 @@ F64 LLViewerMediaImpl::getCPUUsage() const
 
 void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
 {
+	if(mPriority != priority)
+	{
+		LL_INFOS("PluginPriority")
+			<< "changing priority of media id " << mTextureId
+			<< " from " << LLPluginClassMedia::priorityToString(mPriority)
+			<< " to " << LLPluginClassMedia::priorityToString(priority)
+			<< LL_ENDL;
+	}
+	
 	mPriority = priority;
 	
 	if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
@@ -1865,6 +1919,11 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
 		if(mMediaSource)
 		{
 			// Need to unload the media source
+			
+			// First, save off previous media state
+			mPreviousMediaState = mMediaSource->getStatus();
+			mPreviousMediaTime = mMediaSource->getCurrentTime();
+			
 			destroyMediaSource();
 		}
 	}
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index b15314e95448bffdee9c074d54a23b60fc73528d..4f0d39dd801beb9fdb2c1f3f40b39e0678253454 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -123,6 +123,7 @@ class LLViewerMediaImpl
 	void setMediaType(const std::string& media_type);
 	bool initializeMedia(const std::string& mime_type);
 	bool initializePlugin(const std::string& media_type);
+	void loadURI();
 	LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
 	void setSize(int width, int height);
 
@@ -151,6 +152,7 @@ class LLViewerMediaImpl
 	void navigateReload();
 	void navigateHome();
 	void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
+	void navigateInternal();
 	void navigateStop();
 	bool handleKeyHere(KEY key, MASK mask);
 	bool handleUnicodeCharHere(llwchar uni_char);
@@ -174,6 +176,7 @@ class LLViewerMediaImpl
 	bool isMediaPaused();
 	bool hasMedia();
 	bool isMediaFailed() { return mMediaSourceFailed; };
+	void resetPreviousMediaState();
 
 	ECursorType getLastSetCursor() { return mLastSetCursor; };
 	
@@ -287,14 +290,14 @@ class LLViewerMediaImpl
 	bool mUsedInUI;
 	bool mHasFocus;
 	LLPluginClassMedia::EPriority mPriority;
-	bool mDoNavigateOnLoad;
-	bool mDoNavigateOnLoadRediscoverType;
-	bool mDoNavigateOnLoadServerRequest;
+	bool mNavigateRediscoverType;
+	bool mNavigateServerRequest;
 	bool mMediaSourceFailed;
 	F32 mRequestedVolume;
 	bool mIsMuted;
 	bool mNeedsMuteCheck;
-
+	int mPreviousMediaState;
+	F64 mPreviousMediaTime;
 
 private:
 	BOOL mIsUpdated ;
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index b47e0b84067cdef80a8f4ac6dea89bc3e8422016..5d0b77d4fbe824137aa489d0deca858e90671567 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -35,7 +35,7 @@
 
 //LLViewerMediaFocus
 #include "llviewerobjectlist.h"
-#include "llpanelmediahud.h"
+#include "llpanelprimmediacontrols.h"
 #include "llpluginclassmedia.h"
 #include "llagent.h"
 #include "lltoolpie.h"
@@ -106,19 +106,19 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac
 		// We must do this before  processing the media HUD zoom, or it may zoom to the wrong face. 
 		update();
 
-		if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
+		if(mMediaControls.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
 		{
-			mMediaHUD.get()->resetZoomLevel();
-			mMediaHUD.get()->nextZoomLevel();
+			mMediaControls.get()->resetZoomLevel();
+			mMediaControls.get()->nextZoomLevel();
 		}
 	}
 	else
 	{
 		if(mFocusedImplID != LLUUID::null)
 		{
-			if(mMediaHUD.get())
+			if(mMediaControls.get())
 			{
-				mMediaHUD.get()->resetZoomLevel();
+				mMediaControls.get()->resetZoomLevel();
 			}
 
 			gFocusMgr.setKeyboardFocus(NULL);
@@ -327,20 +327,20 @@ void LLViewerMediaFocus::update()
 		// We have an object and impl to point at.
 		
 		// Make sure the media HUD object exists.
-		if(! mMediaHUD.get())
+		if(! mMediaControls.get())
 		{
-			LLPanelMediaHUD* media_hud = new LLPanelMediaHUD();
-			mMediaHUD = media_hud->getHandle();
-			gHUDView->addChild(media_hud);	
+			LLPanelPrimMediaControls* media_controls = new LLPanelPrimMediaControls();
+			mMediaControls = media_controls->getHandle();
+			gHUDView->addChild(media_controls);	
 		}
-		mMediaHUD.get()->setMediaFace(viewer_object, face, media_impl, normal);
+		mMediaControls.get()->setMediaFace(viewer_object, face, media_impl, normal);
 	}
 	else
 	{
 		// The media HUD is no longer needed.
-		if(mMediaHUD.get())
+		if(mMediaControls.get())
 		{
-			mMediaHUD.get()->setMediaFace(NULL, 0, NULL);
+			mMediaControls.get()->setMediaFace(NULL, 0, NULL);
 		}
 	}
 }
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index c77533ba5ae8ab580c47bddbb544095db4823b4c..c1179de39d30734a5633a9e5f3f2fa0017863870 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -40,7 +40,7 @@
 #include "llselectmgr.h"
 
 class LLViewerMediaImpl;
-class LLPanelMediaHUD;
+class LLPanelPrimMediaControls;
 
 class LLViewerMediaFocus : 
 	public LLFocusableElement, 
@@ -88,7 +88,7 @@ class LLViewerMediaFocus :
 
 private:
 	
-	LLHandle<LLPanelMediaHUD> mMediaHUD;
+	LLHandle<LLPanelPrimMediaControls> mMediaControls;
 	
 	LLUUID mFocusedObjectID;
 	S32 mFocusedObjectFace;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 058f44ef5792a515ff000ffcaf05f1fc98109858..864cf9d57bb49800def31ff7cfa4a756189c9482 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3483,7 +3483,6 @@ void set_god_level(U8 god_level)
 {
 	U8 old_god_level = gAgent.getGodLevel();
 	gAgent.setGodLevel( god_level );
-	gIMMgr->refresh();
 	LLViewerParcelMgr::getInstance()->notifyObservers();
 
 	// God mode changes sim visibility
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 791ec07349116ce9d323cff4ac2322a8c0d5c9c2..320f0f83ff9badc54224d33c1a67b30ec51832e8 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -72,7 +72,6 @@
 #include "llviewercontrol.h"
 #include "lldrawpool.h"
 #include "llfirstuse.h"
-#include "llfloateractivespeakers.h"
 #include "llfloateranimpreview.h"
 #include "llfloaterbuycurrency.h"
 #include "llfloaterbuyland.h"
@@ -5680,7 +5679,7 @@ void onCovenantLoadComplete(LLVFS *vfs,
 	LLPanelLandCovenant::updateCovenantText(covenant_text);
 	LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
 
-	LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
+	LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
 	if (panel)
 	{
 		panel->updateCovenantText(covenant_text);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index aea312dd69930ca29e809eab255aa001c40b4e71..9e1ba3f2efbd60b602ddae004470fac5861a8118 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -143,7 +143,6 @@
 #include "llstatview.h"
 #include "llsurface.h"
 #include "llsurfacepatch.h"
-#include "llimview.h"
 #include "lltexlayer.h"
 #include "lltextbox.h"
 #include "lltexturecache.h"
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index a402aff8ab56329277db79f346eb694bf0a9365b..f9c95afc313be7a8336da5cf72f0b13814b24178 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6400,6 +6400,11 @@ LLBBox LLVOAvatar::getHUDBBox() const
 				 ++attachment_iter)
 			{
 				const LLViewerObject* attached_object = (*attachment_iter);
+				if (attached_object == NULL)
+				{
+					llwarns << "HUD attached object is NULL!" << llendl;
+					continue;
+				}
 				// initialize bounding box to contain identity orientation and center point for attached object
 				bbox.addPointLocal(attached_object->getPosition());
 				// add rotated bounding box for attached object
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96fcf61e62899c2b41bce022335a8eb435f3e531
--- /dev/null
+++ b/indra/newview/llvoicechannel.cpp
@@ -0,0 +1,872 @@
+/** 
+ * @file llvoicechannel.cpp
+ * @brief Voice Channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llimview.h"
+#include "llnotifications.h"
+#include "llpanel.h"
+#include "llrecentpeople.h"
+#include "llviewercontrol.h"
+#include "llvoicechannel.h"
+
+
+LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
+LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
+LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
+LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
+
+BOOL LLVoiceChannel::sSuspended = FALSE;
+
+//
+// Constants
+//
+const U32 DEFAULT_RETRIES_COUNT = 3;
+
+
+class LLVoiceCallCapResponder : public LLHTTPClient::Responder
+{
+public:
+	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
+
+	virtual void error(U32 status, const std::string& reason);	// called with bad status codes
+	virtual void result(const LLSD& content);
+
+private:
+	LLUUID mSessionID;
+};
+
+
+void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
+{
+	llwarns << "LLVoiceCallCapResponder::error("
+		<< status << ": " << reason << ")"
+		<< llendl;
+	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+	if ( channelp )
+	{
+		if ( 403 == status )
+		{
+			//403 == no ability
+			LLNotifications::instance().add(
+				"VoiceNotAllowed",
+				channelp->getNotifyArgs());
+		}
+		else
+		{
+			LLNotifications::instance().add(
+				"VoiceCallGenericError",
+				channelp->getNotifyArgs());
+		}
+		channelp->deactivate();
+	}
+}
+
+void LLVoiceCallCapResponder::result(const LLSD& content)
+{
+	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+	if (channelp)
+	{
+		//*TODO: DEBUG SPAM
+		LLSD::map_const_iterator iter;
+		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
+		{
+			llinfos << "LLVoiceCallCapResponder::result got " 
+				<< iter->first << llendl;
+		}
+
+		channelp->setChannelInfo(
+			content["voice_credentials"]["channel_uri"].asString(),
+			content["voice_credentials"]["channel_credentials"].asString());
+	}
+}
+
+//
+// LLVoiceChannel
+//
+LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) : 
+	mSessionID(session_id), 
+	mState(STATE_NO_CHANNEL_INFO), 
+	mSessionName(session_name),
+	mIgnoreNextSessionLeave(FALSE)
+{
+	mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
+
+	if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
+	{
+		// a voice channel already exists for this session id, so this instance will be orphaned
+		// the end result should simply be the failure to make voice calls
+		llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
+	}
+
+	LLVoiceClient::getInstance()->addObserver(this);
+}
+
+LLVoiceChannel::~LLVoiceChannel()
+{
+	// Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
+	if(gVoiceClient)
+	{
+		gVoiceClient->removeObserver(this);
+	}
+	
+	sVoiceChannelMap.erase(mSessionID);
+	sVoiceChannelURIMap.erase(mURI);
+}
+
+void LLVoiceChannel::setChannelInfo(
+	const std::string& uri,
+	const std::string& credentials)
+{
+	setURI(uri);
+
+	mCredentials = credentials;
+
+	if (mState == STATE_NO_CHANNEL_INFO)
+	{
+		if (mURI.empty())
+		{
+			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
+			llwarns << "Received empty URI for channel " << mSessionName << llendl;
+			deactivate();
+		}
+		else if (mCredentials.empty())
+		{
+			LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
+			llwarns << "Received empty credentials for channel " << mSessionName << llendl;
+			deactivate();
+		}
+		else
+		{
+			setState(STATE_READY);
+
+			// if we are supposed to be active, reconnect
+			// this will happen on initial connect, as we request credentials on first use
+			if (sCurrentVoiceChannel == this)
+			{
+				// just in case we got new channel info while active
+				// should move over to new channel
+				activate();
+			}
+		}
+	}
+}
+
+void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+	if (channelURI != mURI)
+	{
+		return;
+	}
+
+	if (type < BEGIN_ERROR_STATUS)
+	{
+		handleStatusChange(type);
+	}
+	else
+	{
+		handleError(type);
+	}
+}
+
+void LLVoiceChannel::handleStatusChange(EStatusType type)
+{
+	// status updates
+	switch(type)
+	{
+	case STATUS_LOGIN_RETRY:
+		//mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
+		LLNotifications::instance().add("VoiceLoginRetry");
+		break;
+	case STATUS_LOGGED_IN:
+		//if (!mLoginNotificationHandle.isDead())
+		//{
+		//	LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
+		//	if (notifyp)
+		//	{
+		//		notifyp->close();
+		//	}
+		//	mLoginNotificationHandle.markDead();
+		//}
+		break;
+	case STATUS_LEFT_CHANNEL:
+		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+		{
+			// if forceably removed from channel
+			// update the UI and revert to default channel
+			LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
+			deactivate();
+		}
+		mIgnoreNextSessionLeave = FALSE;
+		break;
+	case STATUS_JOINING:
+		if (callStarted())
+		{
+			setState(STATE_RINGING);
+		}
+		break;
+	case STATUS_JOINED:
+		if (callStarted())
+		{
+			setState(STATE_CONNECTED);
+		}
+	default:
+		break;
+	}
+}
+
+// default behavior is to just deactivate channel
+// derived classes provide specific error messages
+void LLVoiceChannel::handleError(EStatusType type)
+{
+	deactivate();
+	setState(STATE_ERROR);
+}
+
+BOOL LLVoiceChannel::isActive()
+{ 
+	// only considered active when currently bound channel matches what our channel
+	return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI; 
+}
+
+BOOL LLVoiceChannel::callStarted()
+{
+	return mState >= STATE_CALL_STARTED;
+}
+
+void LLVoiceChannel::deactivate()
+{
+	if (mState >= STATE_RINGING)
+	{
+		// ignore session leave event
+		mIgnoreNextSessionLeave = TRUE;
+	}
+
+	if (callStarted())
+	{
+		setState(STATE_HUNG_UP);
+		// mute the microphone if required when returning to the proximal channel
+		if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
+		{
+			gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
+		}
+	}
+
+	if (sCurrentVoiceChannel == this)
+	{
+		// default channel is proximal channel
+		sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+		sCurrentVoiceChannel->activate();
+	}
+}
+
+void LLVoiceChannel::activate()
+{
+	if (callStarted())
+	{
+		return;
+	}
+
+	// deactivate old channel and mark ourselves as the active one
+	if (sCurrentVoiceChannel != this)
+	{
+		// mark as current before deactivating the old channel to prevent
+		// activating the proximal channel between IM calls
+		LLVoiceChannel* old_channel = sCurrentVoiceChannel;
+		sCurrentVoiceChannel = this;
+		if (old_channel)
+		{
+			old_channel->deactivate();
+		}
+	}
+
+	if (mState == STATE_NO_CHANNEL_INFO)
+	{
+		// responsible for setting status to active
+		getChannelInfo();
+	}
+	else
+	{
+		setState(STATE_CALL_STARTED);
+	}
+}
+
+void LLVoiceChannel::getChannelInfo()
+{
+	// pretend we have everything we need
+	if (sCurrentVoiceChannel == this)
+	{
+		setState(STATE_CALL_STARTED);
+	}
+}
+
+//static 
+LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
+{
+	voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
+	if (found_it == sVoiceChannelMap.end())
+	{
+		return NULL;
+	}
+	else
+	{
+		return found_it->second;
+	}
+}
+
+//static 
+LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
+{
+	voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
+	if (found_it == sVoiceChannelURIMap.end())
+	{
+		return NULL;
+	}
+	else
+	{
+		return found_it->second;
+	}
+}
+
+void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
+{
+	sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
+	mSessionID = new_session_id;
+	sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
+}
+
+void LLVoiceChannel::setURI(std::string uri)
+{
+	sVoiceChannelURIMap.erase(mURI);
+	mURI = uri;
+	sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
+}
+
+void LLVoiceChannel::setState(EState state)
+{
+	switch(state)
+	{
+	case STATE_RINGING:
+		gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+		break;
+	case STATE_CONNECTED:
+		gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
+		break;
+	case STATE_HUNG_UP:
+		gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
+		break;
+	default:
+		break;
+	}
+
+	mState = state;
+}
+
+void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
+{
+	if (state == STATE_CONNECTED)
+	{
+		LLFloaterReg::showInstance("voice_call", mSessionID);
+	}
+	// By checking that current state is CONNECTED we make sure that the call window
+	// has been shown, hence there's something to hide. This helps when user presses
+	// the "End call" button right after initiating the call.
+	// *TODO: move this check to LLFloaterCall?
+	else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
+	{
+		LLFloaterReg::hideInstance("voice_call", mSessionID);
+	}
+}
+
+//static
+void LLVoiceChannel::initClass()
+{
+	sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+}
+
+
+//static 
+void LLVoiceChannel::suspend()
+{
+	if (!sSuspended)
+	{
+		sSuspendedVoiceChannel = sCurrentVoiceChannel;
+		sSuspended = TRUE;
+	}
+}
+
+//static 
+void LLVoiceChannel::resume()
+{
+	if (sSuspended)
+	{
+		if (gVoiceClient->voiceEnabled())
+		{
+			if (sSuspendedVoiceChannel)
+			{
+				sSuspendedVoiceChannel->activate();
+			}
+			else
+			{
+				LLVoiceChannelProximal::getInstance()->activate();
+			}
+		}
+		sSuspended = FALSE;
+	}
+}
+
+
+//
+// LLVoiceChannelGroup
+//
+
+LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) : 
+	LLVoiceChannel(session_id, session_name)
+{
+	mRetries = DEFAULT_RETRIES_COUNT;
+	mIsRetrying = FALSE;
+}
+
+void LLVoiceChannelGroup::deactivate()
+{
+	if (callStarted())
+	{
+		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+	}
+	LLVoiceChannel::deactivate();
+}
+
+void LLVoiceChannelGroup::activate()
+{
+	if (callStarted()) return;
+
+	LLVoiceChannel::activate();
+
+	if (callStarted())
+	{
+		// we have the channel info, just need to use it now
+		LLVoiceClient::getInstance()->setNonSpatialChannel(
+			mURI,
+			mCredentials);
+
+#if 0 // *TODO
+		if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
+		{
+			// Add the party to the list of people with which we've recently interacted.
+			for (/*people in the chat*/)
+				LLRecentPeople::instance().add(buddy_id);
+		}
+#endif
+	}
+}
+
+void LLVoiceChannelGroup::getChannelInfo()
+{
+	LLViewerRegion* region = gAgent.getRegion();
+	if (region)
+	{
+		std::string url = region->getCapability("ChatSessionRequest");
+		LLSD data;
+		data["method"] = "call";
+		data["session-id"] = mSessionID;
+		LLHTTPClient::post(url,
+						   data,
+						   new LLVoiceCallCapResponder(mSessionID));
+	}
+}
+
+void LLVoiceChannelGroup::setChannelInfo(
+	const std::string& uri,
+	const std::string& credentials)
+{
+	setURI(uri);
+
+	mCredentials = credentials;
+
+	if (mState == STATE_NO_CHANNEL_INFO)
+	{
+		if(!mURI.empty() && !mCredentials.empty())
+		{
+			setState(STATE_READY);
+
+			// if we are supposed to be active, reconnect
+			// this will happen on initial connect, as we request credentials on first use
+			if (sCurrentVoiceChannel == this)
+			{
+				// just in case we got new channel info while active
+				// should move over to new channel
+				activate();
+			}
+		}
+		else
+		{
+			//*TODO: notify user
+			llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
+			deactivate();
+		}
+	}
+	else if ( mIsRetrying )
+	{
+		// we have the channel info, just need to use it now
+		LLVoiceClient::getInstance()->setNonSpatialChannel(
+			mURI,
+			mCredentials);
+	}
+}
+
+void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
+{
+	// status updates
+	switch(type)
+	{
+	case STATUS_JOINED:
+		mRetries = 3;
+		mIsRetrying = FALSE;
+	default:
+		break;
+	}
+
+	LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelGroup::handleError(EStatusType status)
+{
+	std::string notify;
+	switch(status)
+	{
+	case ERROR_CHANNEL_LOCKED:
+	case ERROR_CHANNEL_FULL:
+		notify = "VoiceChannelFull";
+		break;
+	case ERROR_NOT_AVAILABLE:
+		//clear URI and credentials
+		//set the state to be no info
+		//and activate
+		if ( mRetries > 0 )
+		{
+			mRetries--;
+			mIsRetrying = TRUE;
+			mIgnoreNextSessionLeave = TRUE;
+
+			getChannelInfo();
+			return;
+		}
+		else
+		{
+			notify = "VoiceChannelJoinFailed";
+			mRetries = DEFAULT_RETRIES_COUNT;
+			mIsRetrying = FALSE;
+		}
+
+		break;
+
+	case ERROR_UNKNOWN:
+	default:
+		break;
+	}
+
+	// notification
+	if (!notify.empty())
+	{
+		LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
+		// echo to im window
+		gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
+	}
+
+	LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelGroup::setState(EState state)
+{
+	// HACK: Open/close the call window if needed.
+	toggleCallWindowIfNeeded(state);
+
+	switch(state)
+	{
+	case STATE_RINGING:
+		if ( !mIsRetrying )
+		{
+			gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+		}
+
+		mState = state;
+		break;
+	default:
+		LLVoiceChannel::setState(state);
+	}
+}
+
+//
+// LLVoiceChannelProximal
+//
+LLVoiceChannelProximal::LLVoiceChannelProximal() : 
+	LLVoiceChannel(LLUUID::null, LLStringUtil::null)
+{
+	activate();
+}
+
+BOOL LLVoiceChannelProximal::isActive()
+{
+	return callStarted() && LLVoiceClient::getInstance()->inProximalChannel(); 
+}
+
+void LLVoiceChannelProximal::activate()
+{
+	if (callStarted()) return;
+
+	LLVoiceChannel::activate();
+
+	if (callStarted())
+	{
+		// this implicitly puts you back in the spatial channel
+		LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+	}
+}
+
+void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+	if (!proximal)
+	{
+		return;
+	}
+
+	if (type < BEGIN_ERROR_STATUS)
+	{
+		handleStatusChange(type);
+	}
+	else
+	{
+		handleError(type);
+	}
+}
+
+void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
+{
+	// status updates
+	switch(status)
+	{
+	case STATUS_LEFT_CHANNEL:
+		// do not notify user when leaving proximal channel
+		return;
+	case STATUS_VOICE_DISABLED:
+		 gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
+		return;
+	default:
+		break;
+	}
+	LLVoiceChannel::handleStatusChange(status);
+}
+
+
+void LLVoiceChannelProximal::handleError(EStatusType status)
+{
+	std::string notify;
+	switch(status)
+	{
+	  case ERROR_CHANNEL_LOCKED:
+	  case ERROR_CHANNEL_FULL:
+		notify = "ProximalVoiceChannelFull";
+		break;
+	  default:
+		 break;
+	}
+
+	// notification
+	if (!notify.empty())
+	{
+		LLNotifications::instance().add(notify, mNotifyArgs);
+	}
+
+	LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelProximal::deactivate()
+{
+	if (callStarted())
+	{
+		setState(STATE_HUNG_UP);
+	}
+}
+
+
+//
+// LLVoiceChannelP2P
+//
+LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) : 
+		LLVoiceChannelGroup(session_id, session_name), 
+		mOtherUserID(other_user_id),
+		mReceivedCall(FALSE)
+{
+	// make sure URI reflects encoded version of other user's agent id
+	setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
+}
+
+void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
+{
+	// status updates
+	switch(type)
+	{
+	case STATUS_LEFT_CHANNEL:
+		if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+		{
+			if (mState == STATE_RINGING)
+			{
+				// other user declined call
+				LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
+			}
+			else
+			{
+				// other user hung up
+				LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
+			}
+			deactivate();
+		}
+		mIgnoreNextSessionLeave = FALSE;
+		return;
+	default:
+		break;
+	}
+
+	LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelP2P::handleError(EStatusType type)
+{
+	switch(type)
+	{
+	case ERROR_NOT_AVAILABLE:
+		LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
+		break;
+	default:
+		break;
+	}
+
+	LLVoiceChannel::handleError(type);
+}
+
+void LLVoiceChannelP2P::activate()
+{
+	if (callStarted()) return;
+
+	LLVoiceChannel::activate();
+
+	if (callStarted())
+	{
+		// no session handle yet, we're starting the call
+		if (mSessionHandle.empty())
+		{
+			mReceivedCall = FALSE;
+			LLVoiceClient::getInstance()->callUser(mOtherUserID);
+		}
+		// otherwise answering the call
+		else
+		{
+			LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
+			
+			// using the session handle invalidates it.  Clear it out here so we can't reuse it by accident.
+			mSessionHandle.clear();
+		}
+
+		// Add the party to the list of people with which we've recently interacted.
+		LLRecentPeople::instance().add(mOtherUserID);
+	}
+}
+
+void LLVoiceChannelP2P::getChannelInfo()
+{
+	// pretend we have everything we need, since P2P doesn't use channel info
+	if (sCurrentVoiceChannel == this)
+	{
+		setState(STATE_CALL_STARTED);
+	}
+}
+
+// receiving session from other user who initiated call
+void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
+{ 
+	BOOL needs_activate = FALSE;
+	if (callStarted())
+	{
+		// defer to lower agent id when already active
+		if (mOtherUserID < gAgent.getID())
+		{
+			// pretend we haven't started the call yet, so we can connect to this session instead
+			deactivate();
+			needs_activate = TRUE;
+		}
+		else
+		{
+			// we are active and have priority, invite the other user again
+			// under the assumption they will join this new session
+			mSessionHandle.clear();
+			LLVoiceClient::getInstance()->callUser(mOtherUserID);
+			return;
+		}
+	}
+
+	mSessionHandle = handle;
+
+	// The URI of a p2p session should always be the other end's SIP URI.
+	if(!inURI.empty())
+	{
+		setURI(inURI);
+	}
+	else
+	{
+		setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
+	}
+	
+	mReceivedCall = TRUE;
+
+	if (needs_activate)
+	{
+		activate();
+	}
+}
+
+void LLVoiceChannelP2P::setState(EState state)
+{
+	// HACK: Open/close the call window if needed.
+	toggleCallWindowIfNeeded(state);
+
+	// you only "answer" voice invites in p2p mode
+	// so provide a special purpose message here
+	if (mReceivedCall && state == STATE_RINGING)
+	{
+		gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
+		mState = state;
+		return;
+	}
+	LLVoiceChannel::setState(state);
+}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
new file mode 100644
index 0000000000000000000000000000000000000000..9966bdd5abff75798ab693808e037dae5196801b
--- /dev/null
+++ b/indra/newview/llvoicechannel.h
@@ -0,0 +1,168 @@
+/** 
+ * @file llvoicechannel.h
+ * @brief Voice channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VOICECHANNEL_H
+#define LL_VOICECHANNEL_H
+
+#include "llhandle.h"
+#include "llvoiceclient.h"
+
+class LLPanel;
+
+class LLVoiceChannel : public LLVoiceClientStatusObserver
+{
+public:
+	typedef enum e_voice_channel_state
+	{
+		STATE_NO_CHANNEL_INFO,
+		STATE_ERROR,
+		STATE_HUNG_UP,
+		STATE_READY,
+		STATE_CALL_STARTED,
+		STATE_RINGING,
+		STATE_CONNECTED
+	} EState;
+
+	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
+	virtual ~LLVoiceChannel();
+
+	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+	virtual void handleStatusChange(EStatusType status);
+	virtual void handleError(EStatusType status);
+	virtual void deactivate();
+	virtual void activate();
+	virtual void setChannelInfo(
+		const std::string& uri,
+		const std::string& credentials);
+	virtual void getChannelInfo();
+	virtual BOOL isActive();
+	virtual BOOL callStarted();
+	const std::string& getSessionName() const { return mSessionName; }
+
+	const LLUUID getSessionID() { return mSessionID; }
+	EState getState() { return mState; }
+
+	void updateSessionID(const LLUUID& new_session_id);
+	const LLSD& getNotifyArgs() { return mNotifyArgs; }
+
+	static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
+	static LLVoiceChannel* getChannelByURI(std::string uri);
+	static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
+	static void initClass();
+	
+	static void suspend();
+	static void resume();
+
+protected:
+	virtual void setState(EState state);
+	void toggleCallWindowIfNeeded(EState state);
+	void setURI(std::string uri);
+
+	std::string	mURI;
+	std::string	mCredentials;
+	LLUUID		mSessionID;
+	EState		mState;
+	std::string	mSessionName;
+	LLSD mNotifyArgs;
+	BOOL		mIgnoreNextSessionLeave;
+	LLHandle<LLPanel> mLoginNotificationHandle;
+
+	typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
+	static voice_channel_map_t sVoiceChannelMap;
+
+	typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
+	static voice_channel_map_uri_t sVoiceChannelURIMap;
+
+	static LLVoiceChannel* sCurrentVoiceChannel;
+	static LLVoiceChannel* sSuspendedVoiceChannel;
+	static BOOL sSuspended;
+};
+
+class LLVoiceChannelGroup : public LLVoiceChannel
+{
+public:
+	LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
+
+	/*virtual*/ void handleStatusChange(EStatusType status);
+	/*virtual*/ void handleError(EStatusType status);
+	/*virtual*/ void activate();
+	/*virtual*/ void deactivate();
+	/*vritual*/ void setChannelInfo(
+		const std::string& uri,
+		const std::string& credentials);
+	/*virtual*/ void getChannelInfo();
+
+protected:
+	virtual void setState(EState state);
+
+private:
+	U32 mRetries;
+	BOOL mIsRetrying;
+};
+
+class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
+{
+public:
+	LLVoiceChannelProximal();
+
+	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+	/*virtual*/ void handleStatusChange(EStatusType status);
+	/*virtual*/ void handleError(EStatusType status);
+	/*virtual*/ BOOL isActive();
+	/*virtual*/ void activate();
+	/*virtual*/ void deactivate();
+
+};
+
+class LLVoiceChannelP2P : public LLVoiceChannelGroup
+{
+public:
+	LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
+
+	/*virtual*/ void handleStatusChange(EStatusType status);
+	/*virtual*/ void handleError(EStatusType status);
+    /*virtual*/ void activate();
+	/*virtual*/ void getChannelInfo();
+
+	void setSessionHandle(const std::string& handle, const std::string &inURI);
+
+protected:
+	virtual void setState(EState state);
+
+private:
+	std::string	mSessionHandle;
+	LLUUID		mOtherUserID;
+	BOOL		mReceivedCall;
+};
+
+#endif  // LL_VOICECHANNEL_H
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 02f63a848be57ee4569085d1cf1d4dd36c2fe482..2834284a9b59a89383bb1e9dcb464cb325c6bb45 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -57,13 +57,13 @@
 #include "llagent.h"
 #include "llcachename.h"
 #include "llimview.h" // for LLIMMgr
-#include "llimpanel.h" // for LLVoiceChannel
 #include "llparcel.h"
 #include "llviewerparcelmgr.h"
 #include "llfirstuse.h"
 #include "llviewerwindow.h"
 #include "llviewercamera.h"
 #include "llvoavatarself.h"
+#include "llvoicechannel.h"
 
 #include "llfloaterfriends.h"  //VIVOX, inorder to refresh communicate panel
 #include "llfloaterchat.h"		// for LLFloaterChat::addChat()
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index 8f74ea29ac7764a79e861f3f5653bb3db54bfa2f..a091028ec2d354ea01e03e28c300fc8751e38031 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -545,7 +545,7 @@ BOOL LLWearable::isDirty() const
 				else
 				{
 					// image found in current image list but not saved image list
-					return FALSE;
+					return TRUE;
 				}
 			}
 		}
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b46b766fc0f052a750409cc1f3d11c60ccd7e6b0..d3366cdcaa523f6f7d7474b649bd1bf6ecf0d2a1 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -144,6 +144,7 @@
   <texture name="Info" file_name="icons/Info.png" preload="false" />
   <texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />
   <texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
+  <texture name="Info_Over" file_name="icons/Info_Over.png" preload="false" />
   <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
 
   <texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index b194b533aff921e299f8a6cc48e8374b79c07205..5cd11ba2929e3a68591333a25b19843b1409962a 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -7,66 +7,56 @@
  save_rect="true"
  title="About [APP_NAME]"
  width="470">
-    <floater.string
-     name="you_are_at">
-        You are at [POSITION]
-    </floater.string>
-    <floater.string
-     name="in_region">
-        in [REGION] located at
-    </floater.string>
-    <floater.string
-     name="CPU">
-        CPU:
-    </floater.string>
-    <floater.string
-     name="Memory">
-        Memory: [MEM] MB
-    </floater.string>
-    <floater.string
-     name="OSVersion">
-        OS Version:
-    </floater.string>
-    <floater.string
-     name="GraphicsCardVendor">
-        Graphics Card Vendor:
-    </floater.string>
-    <floater.string
-     name="GraphicsCard">
-        Graphics Card:
-    </floater.string>
-    <floater.string
-     name="OpenGLVersion">
-        OpenGL Version:
-    </floater.string>
-    <floater.string
-     name="LibCurlVersion">
-        libcurl Version:
-    </floater.string>
-    <floater.string
-     name="J2CDecoderVersion">
-        J2C Decoder Version:
-    </floater.string>
-    <floater.string
-     name="AudioDriverVersion">
-        Audio Driver Version:
-    </floater.string>
-    <floater.string
-     name="none">
-        (none)
-    </floater.string>
-    <floater.string
-     name="LLMozLibVersion">
-        LLMozLib Version:
-    </floater.string>
   <floater.string
-     name="LLQtWebkitVersion">
-        Qt Webkit Version: 4.5.2
+     name="AboutHeader">
+[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+  <floater.string
+     name="AboutCompiler">
+Built with [COMPILER] version [COMPILER_VERSION]
+
+</floater.string>
+  <floater.string
+     name="AboutPosition">
+You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+  <!-- *NOTE: Do not translate text like GPU, Graphics Card, etc -
+       Most PC users who know what these mean will be used to the English versions,
+       and this info sometimes gets sent to support. -->
+  <floater.string
+     name="AboutSystem">
+CPU: [CPU]
+Memory: [MEMORY_MB] MB
+OS Version: [OS_VERSION]
+Graphics Card Vendor: [GRAPHICS_CARD_VENDOR]
+Graphics Card: [GRAPHICS_CARD]
+</floater.string>
+  <floater.string
+     name="AboutDriver">
+Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]
+</floater.string>
+  <floater.string
+     name="AboutLibs">
+OpenGL Version: [OPENGL_VERSION]
+
+libcurl Version: [LIBCURL_VERSION]
+J2C Decoder Version: [J2C_VERSION]
+Audio Driver Version: [AUDIO_DRIVER_VERSION]
+Qt Webkit Version: [QT_WEBKIT_VERSION]
+</floater.string>
+  <floater.string
+     name="none">
+      (none)
   </floater.string>
   <floater.string
-     name="PacketsLost">
-        Packets Lost: [LOST]/[IN] ([PCT]%)
-    </floater.string>
+     name="AboutTraffic">
+Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+</floater.string>
   <tab_container
     follows="all" 
     top="25"
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 072fafd06e3b3de087e214ae1cf70f50759622ad..aa0b4094b43672eedbeb990334751c2a51f1f05f 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -28,7 +28,9 @@
      follows="left|top|right|bottom"
      height="400"
      layout="topleft"
+     font="SansSerifSmall"
      left="1"
+       tab_padding_right="5"
      name="landtab"
      tab_position="top"
      top="20"
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index 520249c2a2136a56891e22cf72a39b5b7b5cc8dc..a713cc32a03ad45314c63545f834d82596cb4e29 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
  can_dock="true"
- can_minimize="true"
- can_close="true" 
+ can_minimize="false"
+ can_close="true"
  center_horiz="true"
- follows="top"
- height="110"
+ follows="bottom"
+ height="152"
  layout="topleft"
  name="camera_floater"
  help_topic="camera_floater"
  save_rect="true"
  save_visibility="true"
- width="105">
+ width="150">
     <floater.string
      name="rotate_tooltip">
         Rotate Camera Around Focus
@@ -25,69 +25,71 @@
         Move Camera Up and Down, Left and Right
     </floater.string>
     <panel
-     border="true"
-     height="79"
+     border="false"
+     height="110"
      layout="topleft"
-     left="0"
+     left="2"
      top="0"
-     mouse_opaque="false" 
+     mouse_opaque="false"
      name="controls"
-     width="105">
-        <joystick_rotate
-         follows="top|left"
-         height="64"
-         image_selected="cam_rotate_in.tga"
-         image_unselected="cam_rotate_out.tga"
-         layout="topleft"
-         left="2"
-         name="cam_rotate_stick"
-         picture_style="true"
-         quadrant="left"
-         scale_image="false"
-         sound_flags="3"
-         tool_tip="Orbit camera around focus"
-         top="15"
-         width="64" />
+     width="148">
         <joystick_track
          follows="top|left"
-         height="64"
-         image_selected="cam_tracking_in.tga"
-         image_unselected="cam_tracking_out.tga"
+         height="78"
+         image_selected="Cam_Tracking_In"
+         image_unselected="Cam_Tracking_Out"
          layout="topleft"
-         left="2"
+         left="45"
          name="cam_track_stick"
          picture_style="true"
          quadrant="left"
          scale_image="false"
          sound_flags="3"
          tool_tip="Move camera up and down, left and right"
-         top="15"
+         top="22"
          visible="false"
-         width="64" />
+         width="78" />
+         <!--TODO: replace with slider, + - images -->
         <joystick_zoom
          follows="top|left"
-         height="64"
-         image_unselected="cam_zoom_out.tga"
+         height="78"
+         image_unselected="ScrollThumb_Vert"
          layout="topleft"
-         left_delta="70"
-         minus_image="cam_zoom_minus_in.tga"
+         left="7"
+         minus_image="ScrollThumb_Vert"
          name="zoom"
          picture_style="true"
-         plus_image="cam_zoom_plus_in.tga"
+         plus_image="ScrollThumb_Vert"
          quadrant="left"
          scale_image="false"
          sound_flags="3"
          tool_tip="Zoom camera toward focus"
-         top_delta="0"
-         width="16" />
+         top="22"
+         width="20" />
+         <joystick_rotate
+         follows="top|left"
+         height="78"
+         image_selected="Cam_Rotate_In"
+         image_unselected="Cam_Rotate_Out"
+         layout="topleft"
+         left="45"
+         name="cam_rotate_stick"
+         picture_style="true"
+         quadrant="left"
+         scale_image="false"
+         sound_flags="3"
+         visible="true"
+         tool_tip="Orbit camera around focus"
+         top="22"
+         width="78" />
         <panel
-         height="70"
+         height="78"
          layout="topleft"
-         left="15"
+         left="36"
          name="camera_presets"
-         top="15"
+         top="30"
          visible="false"
-         width="75">
+         width="78">
             <button
              height="30"
              image_selected="CameraPreset_Rear"
@@ -127,7 +129,7 @@
              name="front_view"
              picture_style="true"
              tool_tip="Front View"
-             top_pad="2"
+             top_pad="5"
              width="30">
                 <click_callback
                  function="CameraPresets.ChangeView"
@@ -151,21 +153,21 @@
         </panel>
     </panel>
     <panel
-     border="true"
-     height="25"
+     border="false"
+     height="42"
      layout="topleft"
-     left="0"
-     top_pad="1"
+     left="2"
+     top_pad="0"
      name="buttons"
-     width="105">
+     width="148">
         <button
          height="23"
          label=""
          layout="topleft"
-         left="2"
+         left="23"
          is_toggle="true"
          image_overlay="Cam_Orbit_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="orbit_btn"
          tab_stop="false"
          tool_tip="Orbit camera"
@@ -179,7 +181,7 @@
          left_pad="0"
          is_toggle="true"
          image_overlay="Cam_Pan_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="pan_btn"
          tab_stop="false"
          tool_tip="Pan camera"
@@ -191,7 +193,7 @@
          layout="topleft"
          left_pad="0"
          image_overlay="Cam_Avatar_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="avatarview_btn"
          tab_stop="false"
          tool_tip="See as avatar"
@@ -204,12 +206,11 @@
          left_pad="0"
          is_toggle="true"
          image_overlay="Cam_FreeCam_Off"
-         image_selected="PushButton_Selected_Press" 
+         image_selected="PushButton_Selected_Press"
          name="freecamera_btn"
          tab_stop="false"
          tool_tip="View object"
          width="25">
         </button>
-        
     </panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 0bd4b441c6165533ebb39d7e7026526617b15abd..d24d1b706455823a3379086cd7e46bf80b5ae93f 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -14,7 +14,7 @@
  save_rect="true"
  title="Nearby Chat"
  save_visibility="true"
- single_instance="true" 
+ single_instance="true"
  width="320">
             <chat_history
              allow_html="true" 
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 5f70f09a344b4a7104fa46f0eb3bec9bea27b4e5..69525d48d27d0a1d6ab8d5e05285969ec4ce53d7 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -34,7 +34,7 @@
      type="string"
      length="1"
      follows="left|top"
-     font="SansSerif"
+     font="SansSerifSmall"
      height="16"
      layout="topleft"
      left_pad="7"
@@ -44,6 +44,7 @@
     </text>
     <button
      height="23"
+     font="SansSerifSmall"  
      label="L$1"
      label_selected="L$1"
      layout="topleft"
@@ -53,7 +54,8 @@
      width="80" />
     <button
      height="23"
-     label="L$5"
+     label="L$1"
+     font="SansSerif"  
      label_selected="L$5"
      layout="topleft"
      left_pad="15"
@@ -62,6 +64,7 @@
     <button
      height="23"
      label="L$10"
+     font="SansSerifHuge"  
      label_selected="L$10"
      layout="topleft"
      left="25"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
index 8cdafe110a79acba7d98ce8edcd102d2edaec618..d2b8455eabede075387a659c26f6b2e1534a501f 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -83,7 +83,7 @@
         Loading...
     </text_editor>
     <button
-     follows="left|bottom"
+     follows="right|bottom"
      height="22"
      label="Save"
      label_selected="Save"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index abde4ba5fad6e541578000b1faefe9c60999185f..884532c7a3e2af5e8f4d795e2ca36afe44c79f65 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -14,19 +14,19 @@
      allow_no_texture="true"
      default_image_name="None"
      follows="left|top"
-     height="125"
+     height="150"
      layout="topleft"
-     left="10"
-     name="screenshot"
-     top="23"
-     width="160" />
+     left="60"
+     name=""
+     top="15"
+     width="220" />
     <check_box
      height="15"
      label="Use this screenshot"
      layout="topleft"
-     left_pad="5"
+     left="8"
      name="screen_check"
-     top="120"
+     top_pad="-12"
      width="116" />
     <text
      type="string"
@@ -38,8 +38,8 @@
      layout="topleft"
      left="10"
      name="reporter_title"
-     top="140"
-     width="60">
+     top_pad="0"
+     width="100">
         Reporter:
     </text>
     <text
@@ -48,24 +48,25 @@
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="10"
+     left_pad="5"
      name="reporter_field"
      top_delta="0"
-     width="193">
-        Loremipsum Dolorsitamut
+     use_ellipses="true"
+     width="200">
+        Loremipsum Dolorsitamut Longnamez
     </text>
     <text
      type="string"
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="10"
      name="sim_title"
-     top_pad="5"
-     width="60">
+     top_pad="2"
+     width="100">
         Region:
     </text>
     <text
@@ -74,10 +75,11 @@
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="2"
+     left_pad="5"
      name="sim_field"
      top_delta="0"
-     width="193">
+     use_ellipses="true"
+     width="200">
         Region Name
     </text>
     <text
@@ -85,13 +87,13 @@
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="10"
      name="pos_title"
-     top_pad="5"
-     width="50">
+     top_pad="2"
+     width="100">
         Position:
     </text>
     <text
@@ -100,10 +102,10 @@
      follows="left|top"
      height="16"
      layout="topleft"
-     left_pad="12"
+     left_pad="5"
      name="pos_field"
      top_delta="0"
-     width="193">
+     width="200">
         {128.1, 128.1, 15.4}
     </text>
  <text
@@ -114,7 +116,7 @@
      layout="topleft"
      left="10"
      name="select_object_label"
-     top_pad="5"
+     top_pad="2"
      width="310">
         Click the button, then the abusive object:
     </text>
@@ -133,13 +135,13 @@
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="48"
      name="object_name_label"
      top_delta="0"
-     width="60">
+     width="80">
         Object:
     </text>
     <text
@@ -151,7 +153,8 @@
      left_pad="6"
      name="object_name"
      top_delta="0"
-     width="157">
+     use_ellipses="true"
+     width="185">
         Consetetur Sadipscing
     </text>
     <text
@@ -159,13 +162,13 @@
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="48"
      name="owner_name_label"
      top_pad="0"
-     width="60">
+     width="80">
         Owner:
     </text>
     <text
@@ -177,8 +180,9 @@
      left_pad="6"
      name="owner_name"
      top_delta="0"
-     width="157">
-        Hendrerit Vulputate
+     use_ellipses="true"
+     width="185">
+        Hendrerit Vulputate Kamawashi Longname
     </text>
     <combo_box
      height="23"
@@ -349,8 +353,8 @@
      type="string"
      length="1"
      follows="left|top"
-     height="16"
-     font.name="SansSerif" 
+     height="14"
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left_delta="0"
@@ -368,11 +372,10 @@
      left_delta="0"
      max_length="32"
      name="abuser_name_edit"
-     top_pad="2"
+     top_pad="0"
      width="195" />
     <button
      height="23"
-     font="SansSerifSmall"
      label="Choose"
      layout="topleft"
      left_pad="5"
@@ -394,13 +397,13 @@
      type="string"
      length="1"
      follows="left|top"
-     height="16"
-     font.name="SansSerif" 
+     height="14"
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left="10"
      name="abuser_name_title2"
-     top_pad="5"
+     top_pad="2"
      width="313">
         Location of Abuse:
     </text>
@@ -413,19 +416,19 @@
      left="10"
      max_length="256"
      name="abuse_location_edit"
-     top_pad="2"
+     top_pad="0"
      width="313" />
     <text
      type="string"
      length="1"
      follows="left|top"
      height="16"
-     font.name="SansSerif" 
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left_delta="0"
      name="sum_title"
-     top_pad="5"
+     top_pad="2"
      width="313">
         Summary:
     </text>
@@ -438,14 +441,14 @@
      left_delta="0"
      max_length="64"
      name="summary_edit"
-     top_pad="2"
+     top_pad="0"
      width="313" />
     <text
      type="string"
      length="1"
      follows="left|top"
-     height="16"
-     font.name="SansSerif" 
+     height="14"
+     font.name="SansSerif"
      font.style="BOLD"
      layout="topleft"
      left_delta="0"
@@ -461,9 +464,9 @@
      height="16"
      layout="topleft"
      name="bug_aviso"
-     left_pad="0"
+     left_pad="10"
      width="200">
-        Please be as specific as possible.
+        Please be as specific as possible
     </text>
     <text_editor
      follows="left|top"
@@ -479,16 +482,15 @@
      type="string"
      length="1"
      follows="left|top"
-     height="50"
+     height="30"
      layout="topleft"
      left="10"
-     font.name="SansSerif" 
-     font.style="BOLD"
+     font.name="SansSerifSmall"
      name="incomplete_title"
-     top_pad="5"
+     top_pad="2"
      word_wrap="true"
      width="313">
-        Note: Incomplete reports won't be investigated.
+        * Incomplete reports won't be investigated
     </text>
      <button
      left="80"
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 8305452c850b968c296282dad8939c005b6f237c..c33ab8aa70232dadd7b3daf4e3cab9400bfedf1b 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -114,16 +114,59 @@
         Escaped greater than &gt;
     </text>
     <text
-     type="string"
-     length="1"
-     bottom="390"
-     label="N"
-     layout="topleft"
-     left="10"
-     name="floater_map_north"
-     right="30"
-     text_color="1 1 1 0.7"
-     top="370">
-        N
-    </text>
+   type="string"
+   length="1"
+   bottom="390"
+   label="N"
+   layout="topleft"
+   left="10"
+   name="right_aligned_text"
+   width="380"
+   halign="right" 
+   text_color="1 1 1 0.7"
+   top_pad="10">
+    Right aligned text
+  </text>
+  <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="center"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+    Centered text
+  </text>
+  <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="left"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+    Left aligned text
+  </text>
+  <text
+   type="string"
+   length="1"
+   bottom="390"
+   label="N"
+   layout="topleft"
+   left="10"
+   name="floater_map_north"
+   right="30"
+   text_color="1 1 1 0.7"
+   top="370">
+    N
+  </text>
+
 </floater>
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
index cc17e9dd4b7acfef22d5166aa3453775da984669..eedb4383bbf830af85bacdd688f9b018e15307aa 100644
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
@@ -23,9 +23,14 @@
        parameter="sort_status" />
   </menu_item_check>
   <menu_item_separator layout="topleft" />
-  <menu_item_call name="view_icons" label="View People Icons">
-    <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="view_icons" />
-  </menu_item_call>
+  <menu_item_check name="view_icons" label="View People Icons">
+    <menu_item_check.on_click
+     function="People.Friends.ViewSort.Action"
+     parameter="view_icons" />
+    <menu_item_check.on_check
+     function="CheckControl"
+     parameter="FriendsListShowIcons" />
+  </menu_item_check>
   <menu_item_call name="organize_offline" label="Organize Offline Friends">
     <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" />
   </menu_item_call>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
index f91a9613886e57546bee93e13ced298e0d202ba6..c002cd078f7c2d2bf7bf73cb4b72917e66df9f90 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
@@ -12,9 +12,14 @@
     <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_distance" />
   </menu_item_call>
   <menu_item_separator layout="topleft" />
-  <menu_item_call name="view_icons" label="View People Icons">
-    <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" />
-  </menu_item_call>
+  <menu_item_check name="view_icons" label="View People Icons">
+    <menu_item_check.on_click
+     function="People.Nearby.ViewSort.Action"
+     parameter="view_icons" />
+    <menu_item_check.on_check
+     function="CheckControl"
+     parameter="NearbyListShowIcons" />
+  </menu_item_check>
   <menu_item_separator layout="topleft" />
   <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
     <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
index d09871cff3a6262ee6b00a3d3ac4fa950e6226b5..cfd6dc78b601feac8a46b8dcd265a83b076dfaa4 100644
--- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
@@ -23,9 +23,14 @@
        parameter="sort_name" />
   </menu_item_check>
   <menu_item_separator layout="topleft" />
-  <menu_item_call name="view_icons" label="View People Icons">
-    <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" />
-  </menu_item_call>
+  <menu_item_check name="view_icons" label="View People Icons">
+    <menu_item_check.on_click
+     function="People.Recent.ViewSort.Action"
+     parameter="view_icons" />
+    <menu_item_check.on_check
+     function="CheckControl"
+     parameter="RecentListShowIcons" />
+  </menu_item_check>
   <menu_item_separator layout="topleft" />
   <menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
     <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
diff --git a/indra/newview/skins/default/xui/en/menu_place_add_button.xml b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e3a39a1242748c8b73874fc851b73cdd77f1db4a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_folder_gear"
+ visible="false">
+    <menu_item_call
+     label="Add Folder"
+     layout="topleft"
+     name="add_folder">
+        <on_click
+         function="Places.LandmarksGear.Add.Action"
+         parameter="category" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="category" />
+    </menu_item_call>
+    <menu_item_call
+     label="Add Landmark"
+     layout="topleft"
+     name="add_landmark">
+        <on_click
+         function="Places.LandmarksGear.Add.Action"
+         parameter="add_landmark" />
+    </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8db745fab711e90a2cda2a9478e2c61a67d19920
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="panel_im_control_panel"
+ width="146"
+ height="215"
+ border="false">
+    <avatar_list
+     color="DkGray2"
+     follows="left|top|right|bottom"
+     height="130"
+     ignore_online_status="true"
+     layout="topleft"
+     left="3"
+     name="speakers_list"
+     opaque="false"
+     top="10"
+     width="140" />
+    <button
+     name="call_btn"
+     label="Call"
+     width="90"
+     height="20" />
+    <button
+     name="end_call_btn"
+     label="End Call"
+     width="90"
+     height="20" 
+     visible="false"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
index 9767a673f64e3bdda1afa1956fc9bcc3ab82b6d4..15b6b2a00db2467433af09e1e3512bc9cffa2952 100644
--- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -7,12 +7,14 @@
     <avatar_list
      color="DkGray2"
      follows="left|top|right|bottom"
-     height="150"
+     height="130"
+     ignore_online_status="true"
      layout="topleft"
      left="3"
      name="speakers_list"
+     opaque="false"
      top="10"
-     width="140"/>
+     width="140" />
     <button
      name="group_info_btn"
      label="Group Info"
@@ -24,4 +26,10 @@
      label="Call"
      width="90"
      height="20" />
+    <button
+     name="end_call_btn"
+     label="End Call"
+     width="90"
+     height="20" 
+     visible="false"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 75ded4f249a104686ee0232ae1a686a0864e7be1..af1919bd8f332ff195495df6fdabb2751f1da622 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -486,7 +486,7 @@ things in this group. There&apos;s a broad variety of Abilities.
         </panel>
     </tab_container>
     <panel
-     height="170"
+     height="190"
      layout="topleft"
      follows="left|top"
      left="10"
@@ -556,7 +556,7 @@ things in this group. There&apos;s a broad variety of Abilities.
         </scroll_list>
     </panel>
     <panel
-     height="215"
+     height="252"
      layout="topleft"
      left_delta="0"
      name="roles_footer"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 7dc94d1141dbacbfb5d9a7011c290566f9044adf..dca52def495782eb636b7658951b131e9403d68c 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <panel name="panel_im_control_panel"
        width="96"
-       height="215"
+       height="225"
        border="false">
 
   <avatar_icon name="avatar_icon"
@@ -24,6 +24,13 @@
           width="90"
           height="20" />
 
+    <button
+     height="20"
+     label="End Call"
+     name="end_call_btn"
+     visible="false"
+     width="90" />
+
   <button name="share_btn"
           label="Share"
           width="90"
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index c33f68eaf7ac4315ca57b6e54035438e8b593819..5293043ba7df9d8ed2ed156d076f7e5e44ed28d0 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -114,22 +114,10 @@
          image_disabled="AddItem_Disabled"
          layout="topleft"
          left_pad="5"
-         name="add_landmark_btn"
+         name="add_btn"
          picture_style="true"
          tool_tip="Add new landmark"
          width="18" />
-        <button
-         follows="bottom|left"
-         height="18"
-         image_selected="AddItem_Press"
-         image_unselected="AddItem_Off"
-         image_disabled="AddItem_Disabled"
-         layout="topleft"
-         left_pad="5"
-         name="add_folder_btn"
-         picture_style="true"
-         tool_tip="Add new folder"
-         width="18" />
         <dnd_button
          follows="bottom|right"
          height="18"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 7b19ab1a1cb61b7ff8286b904d071eb9ea300d96..69089e0e262c17e2c8282f052a4ec61194e8db11 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -49,11 +49,13 @@ background_visible="true"
      height="500"
      layout="topleft"
      left="10"
+       font="SansSerifBigBold"
      name="tabs"
      tab_min_width="70"
      tab_height="30"
      tab_position="top"
      top_pad="10"
+     halign="center"  
      width="313">
         <panel
          follows="all"
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b21fbc1795fe05e2dd8b1989f97745668e9b4b7c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -0,0 +1,594 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+	follows="left|right|top|bottom"
+	name="MediaControls"
+	bg_alpha_color="1 1 1 0"
+	height="160"
+	layout="topleft"
+	mouse_opaque="false"
+	width="800">
+  <panel
+	  name="media_region"
+	  bottom="125"
+	  follows="left|right|top|bottom"
+	  layout="topleft"
+	  left="20"
+	  mouse_opaque="false"
+	  right="-20"
+	  top="20" />
+  <layout_stack
+	  follows="left|right|bottom"
+	  height="32"
+	  layout="topleft"
+	  animate="false"
+	  left="0"
+	  orientation="horizontal"
+	  top="96">
+	<!-- outer layout_panels center the inner one -->
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+	<panel
+		name="media_progress_indicator"
+		height="22"
+		layout="topleft"
+		left="0"
+		top="0"
+		auto_resize="false"
+		user_resize="false"
+		min_width="100"
+		width="200">
+	  <progress_bar
+		  name="media_progress_bar"
+		  color_bar="1 1 1 0.96"
+		  follows="left|right|top"
+		  height="16"
+		  layout="topleft"
+		  left="0"
+		  tool_tip="Media is Loading"/>
+	</panel>
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+  </layout_stack>
+  <layout_stack
+	  name="media_controls"
+	  follows="left|right"
+	  animate="false"
+	  height="32"
+	  layout="topleft"
+	  left="0"
+	  orientation="horizontal"
+	  top="128">
+	<!-- outer layout_panels center the inner one -->
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+	<layout_panel
+		name="back"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="22"
+		width="22"
+		top="4">
+	  <button
+		  auto_resize="false"
+		  height="22"
+		  image_selected="media_btn_back.png"
+		  image_unselected="media_btn_back.png"
+		  layout="topleft"
+		  tool_tip="Step back"
+		  picture_style="true"
+		  width="22"
+		  top_delta="4">
+		<button.commit_callback
+			function="MediaCtrl.Back" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="fwd"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="10"
+		min_width="17"
+		width="17">
+	  <button
+		  height="22"
+		  image_selected="media_btn_forward.png"
+		  image_unselected="media_btn_forward.png"
+		  layout="topleft"
+		  tool_tip="Step forward"
+		  picture_style="true"
+		  top_delta="0"
+		  min_width="17"
+		  width="17">
+		<button.commit_callback
+			function="MediaCtrl.Forward" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="home"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="-2"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_home.png"
+		  image_unselected="media_btn_home.png"
+		  layout="topleft"
+		  tool_tip="Home page"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Home" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="media_stop"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="2"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="button_anim_stop.tga"
+		  image_unselected="button_anim_stop.tga"
+		  layout="topleft"
+		  tool_tip="Stop media"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Stop" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="reload"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="6"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_reload.png"
+		  image_unselected="media_btn_reload.png"
+		  layout="topleft"
+		  tool_tip="Reload"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Reload" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="stop"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="10"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_stoploading.png"
+		  image_unselected="media_btn_stoploading.png"
+		  layout="topleft"
+		  picture_style="true"
+		  tool_tip = "Stop loading"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Stop" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="play"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="14"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="button_anim_play.tga"
+		  image_unselected="button_anim_play.tga"
+		  layout="topleft"
+		  tool_tip = "Play media"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Play" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="pause"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		top="18"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="button_anim_pause.tga"
+		  image_unselected="button_anim_pause.tga"
+		  layout="topleft"
+		  tool_tip = "Pause media"
+		  picture_style="true">
+		<button.commit_callback
+			function="MediaCtrl.Pause" />
+	  </button>
+	</layout_panel>
+	<!-- media URL entry  -->
+	<layout_panel
+		name="media_address"
+		auto_resize="true"
+		user_resize="false"
+		height="22"
+		follows="left|right|bottom"
+		layout="topleft"
+		width="190"
+		min_width="90">
+	  <!--
+		  RE-ENABLE THIS WHEN WE HAVE A HISTORY DROP-DOWN AGAIN
+
+<combo_box
+name="media_address_url"
+allow_text_entry="true"
+height="22"
+layout="topleft"
+max_chars="1024"
+tool_tip = "Media URL"
+<combo_box.commit_callback
+function="MediaCtrl.CommitURL" />
+</combo_box>
+	  -->
+	  <line_editor 
+		  name="media_address_url"
+		  follows="left|right" 
+		  height="22"
+		  top="0"
+		  tool_tip="Media URL"
+		  text_pad_right="16"> 
+		<line_editor.commit_callback
+			function="MediaCtrl.CommitURL"/>
+	  </line_editor>
+	  <layout_stack
+		  animate="false"
+		  follows="right"
+		  width="32"
+		  min_width="32"
+		  height="16"
+		  top="3"
+		  orientation="horizontal"
+		  left_pad="-38">
+		<icon
+			name="media_whitelist_flag"
+			follows="top|right"
+			height="16"
+			image_name="smicon_warn.tga"
+			layout="topleft"
+			tool_tip="White List enabled"
+			min_width="16"
+			width="16" />
+		<icon
+			name="media_secure_lock_flag"
+			height="16"
+			image_name="inv_item_eyes.tga"
+			layout="topleft"
+			tool_tip="Secured Browsing"
+			min_width="16"
+			width="16" />
+	  </layout_stack>
+	</layout_panel>
+	<layout_panel
+		name="media_play_position"
+		auto_resize="true"
+		user_resize="false"
+		follows="left|right|top|bottom"
+		layout="topleft"
+		min_width="100"
+		width="200">
+	  <slider_bar
+		  name="media_play_slider"
+		  follows="left|right|top"
+		  height="22"
+		  increment="0.05"
+		  initial_value="0.5"
+		  layout="topleft"
+		  tool_tip="Movie play progress"
+		  min_width="100"
+		  width="200">
+		<slider_bar.commit_callback
+			function="MediaCtrl.JumpProgress" />
+	  </slider_bar>
+	</layout_panel>
+	<layout_panel
+		name="media_volume"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		height="24"
+		min_width="24"
+		width="24">
+	  <button
+		  name="media_volume_button"
+		  height="22"
+		  image_selected="icn_speaker-muted_dark.tga"
+		  image_unselected="icn_speaker_dark.tga"
+		  is_toggle="true"
+		  layout="topleft"
+		  scale_image="false" 
+		  picture_style="true"
+		  tool_tip="Mute This Media"
+		  top_delta="22"
+		  min_width="24"
+		  width="24" >
+		<button.commit_callback
+			function="MediaCtrl.ToggleMute" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="volume_up"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="20"
+		height="14"
+		width="20">
+	  <button
+		  top="-3"
+		  height="14"
+		  image_selected="media_btn_scrollup.png"
+		  image_unselected="media_btn_scrollup.png"
+		  layout="topleft"
+		  tool_tip="Volume up"
+		  picture_style="true"
+		  scale_image="true"
+		  min_width="20"
+		  width="20" >
+		<button.commit_callback
+			function="MediaCtrl.CommitVolumeUp" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		name="volume_down"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="20"
+		height="14"
+		width="20">
+	  <button
+		  top="-5"
+		  height="14"
+		  image_selected="media_btn_scrolldown.png"
+		  image_unselected="media_btn_scrolldown.png"
+		  layout="topleft"
+		  tool_tip="Volume down"
+		  picture_style="true"
+		  scale_image="true"
+		  min_width="20"
+		  width="20">
+		<button.commit_callback
+			function="MediaCtrl.CommitVolumeDown" />
+	  </button>
+	</layout_panel>
+	<!-- Scroll pad -->
+	<layout_panel
+		name="media_panel_scroll"
+		auto_resize="false"
+		user_resize="false"
+		height="32"
+		follows="left|right|top|bottom"
+		layout="topleft"
+		min_width="32"
+		width="32">
+	  <icon
+		  height="32"
+		  image_name="media_panel_scrollbg.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="32"
+		  width="32" />
+	  <button
+		  name="scrollup"
+		  height="8"
+		  image_selected="media_btn_scrollup.png"
+		  image_unselected="media_btn_scrollup.png"
+		  layout="topleft"
+		  tool_tip="Scroll up"
+		  picture_style="true"
+		  scale_image="false"
+		  left="12"
+		  top_delta="4"
+		  min_width="8"
+		  width="8" />
+	  <button
+		  name="scrollleft"
+		  height="8"
+		  image_selected="media_btn_scrollleft.png"
+		  image_unselected="media_btn_scrollleft.png"
+		  layout="topleft"
+		  left="3"
+		  tool_tip="Scroll left"
+		  picture_style="true"
+		  scale_image="false"
+		  top="12"
+		  min_width="8"
+		  width="8" />
+	  <button
+		  name="scrollright"
+		  height="8"
+		  image_selected="media_btn_scrollright.png"
+		  image_unselected="media_btn_scrollright.png"
+		  layout="topleft"
+		  left_pad="9"
+		  tool_tip="Scroll right"
+		  picture_style="true"
+		  scale_image="false"
+		  top_delta="0"
+		  min_width="8"
+		  width="8" />
+	  <button
+		  name="scrolldown"
+		  height="8"
+		  image_selected="media_btn_scrolldown.png"
+		  image_unselected="media_btn_scrolldown.png"
+		  layout="topleft"
+		  left="12"
+		  tool_tip="Scroll down"
+		  picture_style="true"
+		  scale_image="false"
+		  top="20"
+		  min_width="8"
+		  width="8" />
+	</layout_panel>
+	<layout_panel
+		name="zoom_frame"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		height="28"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_optimalzoom.png"
+		  image_unselected="media_btn_optimalzoom.png"
+		  layout="topleft"
+		  tool_tip="Zoom"
+		  picture_style="true"
+		  min_width="22"
+		  width="22">
+		<button.commit_callback
+			function="MediaCtrl.Zoom" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="new_window"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="22"
+		width="22">
+	  <button
+		  height="22"
+		  image_selected="media_btn_newwindow.png"
+		  image_unselected="media_btn_newwindow.png"
+		  layout="topleft"
+		  tool_tip = "Open URL in browser"
+		  picture_style="true"
+		  top_delta="-3"
+		  min_width="24"
+		  width="24" >
+		<button.commit_callback
+			function="MediaCtrl.Open" />
+	  </button>
+	</layout_panel>
+<!--
+	<panel
+		height="22"
+		layout="topleft"
+		auto_resize="false"
+		min_width="3"
+		width="3">
+	  <icon
+		  height="22"
+		  image_name="media_panel_divider.png"
+		  layout="topleft"
+		  top="0"
+		  min_width="3"
+		  width="3" />
+	</panel>
+-->
+	<layout_panel
+		name="close"
+		auto_resize="false"
+		user_resize="false"
+		layout="topleft"
+		min_width="21"
+		width="21" >
+	  <button
+		  height="22"
+		  image_selected="media_btn_done.png"
+		  image_unselected="media_btn_done.png"
+		  layout="topleft"
+		  tool_tip ="Close media control"
+		  picture_style="true"
+		  top_delta="-4"
+		  width="21" >
+		<button.commit_callback
+			function="MediaCtrl.Close" />
+	  </button>
+	</layout_panel>
+	<layout_panel
+		width="0"
+		layout="topleft"
+		user_resize="false" />
+  </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 81bc12c33ccc18e0b599c6254c797ade9d5fd44c..4eacd72a7d3acaccbeac4261326f70b7952567f4 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -61,9 +61,7 @@
 	<string name="TooltipFlagGroupScripts">Group Scripts</string>
 	<string name="TooltipFlagNoScripts">No Scripts</string>
 	<string name="TooltipLand">Land:</string>
-	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>	
-	<string name="TooltipAltLeft">Alt+&#8592; for previous tab</string>	
-	<string name="TooltipAltRight">Alt+&#8594; for next tab</string>	
+	<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
 
 	<!-- tooltips for Urls -->
 	<string name="TooltipHttpUrl">Click to view this web page</string>
@@ -264,10 +262,6 @@
 	<string name="TrackYourCamera">Track your camera</string>
 	<string name="ControlYourCamera">Control your camera</string>
 
-	<!-- IM -->
-	<string name="IM_logging_string">-- Instant message logging enabled --</string>
-	<string name="Unnamed">(Unnamed)</string>
-	
 	<!-- Sim Access labels -->
 	<string name="SIM_ACCESS_PG">PG</string>
 	<string name="SIM_ACCESS_MATURE">Mature</string>
@@ -2022,15 +2016,14 @@ this texture in your inventory
 	<string name="IMTeen">teen</string>
 	
 	<!-- floater region info -->
+	<!-- The following will replace variable [ALL_ESTATES] in notifications EstateAllowed*, EstateBanned*, EstateManager* -->
 	<string name="RegionInfoError">error</string>
 	<string name="RegionInfoAllEstatesOwnedBy">
-		all estates
-owned by [OWNER]
+		all estates owned by [OWNER]
 	</string>
-	<string name="RegionInfoAllEstatesYouOwn">all estates you owned</string>
+	<string name="RegionInfoAllEstatesYouOwn">all estates that you own</string>
 	<string name="RegionInfoAllEstatesYouManage">
-		all estates that
-you managed for [OWNER]
+		all estates that you manage for [OWNER]
 	</string>
 	<string name="RegionInfoAllowedResidents">Allowed residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string>
 	<string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
@@ -2884,7 +2877,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 	  Failed to start viewer
 	</string>
 
-  <!-- IM system messages -->
+	<!-- IM system messages -->
+	<string name="IM_logging_string">-- Instant message logging enabled --</string>
+	<string name="IM_typing_start_string">[NAME] is typing...</string>
+	<string name="Unnamed">(Unnamed)</string>
+	<string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string>
+	<string name="IM_unavailable_text_label">Text chat is not available for this call.</string>
+
+
   <string name="ringing-im">
     Joining Voice Chat...
   </string>
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
index b72d59524e0304fbf467498ffc46f7df096ce8cd..ea6997ebd54940039a796a39d678b28e221d5cf0 100644
--- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -4,8 +4,8 @@
     message_separator="panel_chat_separator.xml"
     left_text_pad="10"
 	right_text_pad="15"
-    left_widget_pad="5"
-	rigth_widget_pad="10"
+    left_widget_pad="0"
+	right_widget_pad="10"
 	max_length="2147483647"
 	enabled="false"
 	track_bottom="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
index 89e442baec8ebccd71a8bc65746115b3ec7593d4..ab4ad940893a8819ad6e0f585ee0a29ecfd1f2d9 100644
--- a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
@@ -23,7 +23,8 @@
                               image_selected="DropDown_Selected"
                               image_disabled="DropDown_Disabled"
                               image_disabled_selected="DropDown_Disabled_Selected" />
-  <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor" />
+  <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor"
+                                scroll_bar_bg_visible="true" />
   <gesture_combo_box.combo_editor name="Combo Text Entry"
                           select_on_focus="true"
                           font="SansSerifSmall" />
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
index 2fe5f517a2359240686231248ce45d9752b8f735..7d10df1af702ca556bac5e99e6785ea77325a0e6 100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <tab_container tab_min_width="60"
                tab_max_width="150"
+               font_halign="left"
                tab_height="16">
   <first_tab tab_top_image_unselected="TabTop_Left_Off"
                tab_top_image_selected="TabTop_Left_Selected"