diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 8609ba8b1c6d4b9c0269350e0161852d19ad9f52..bb03f47f46f4207e8c8668e1822787b45b36ba1c 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -65,6 +65,20 @@ void LLAvatarList::toggleIcons()
 	}
 }
 
+void LLAvatarList::setSpeakingIndicatorsVisible(bool visible)
+{
+	// Save the new value for new items to use.
+	mShowSpeakingIndicator = visible;
+	
+	// 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)->setSpeakingIndicatorVisible(mShowSpeakingIndicator);
+	}
+}
+
 static bool findInsensitive(std::string haystack, const std::string& needle_upper)
 {
     LLStringUtil::toUpper(haystack);
@@ -81,6 +95,7 @@ LLAvatarList::Params::Params()
 , show_last_interaction_time("show_last_interaction_time", false)
 , show_info_btn("show_info_btn", true)
 , show_profile_btn("show_profile_btn", true)
+, show_speaking_indicator("show_speaking_indicator", true)
 {
 }
 
@@ -94,6 +109,7 @@ LLAvatarList::LLAvatarList(const Params& p)
 , mShowIcons(true)
 , mShowInfoBtn(p.show_info_btn)
 , mShowProfileBtn(p.show_profile_btn)
+, mShowSpeakingIndicator(p.show_speaking_indicator)
 {
 	setCommitOnSelectionChange(true);
 
@@ -295,6 +311,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is
 	item->setAvatarIconVisible(mShowIcons);
 	item->setShowInfoBtn(mShowInfoBtn);
 	item->setShowProfileBtn(mShowProfileBtn);
+	item->setSpeakingIndicatorVisible(mShowSpeakingIndicator);
 
 	addItem(item, id, pos);
 }
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index 195d9e5b550135766a90379f0c9c3e44a5dc5ea3..490f93e5015e2e96b2118a9d4b5374d105435422 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -61,6 +61,7 @@ class LLAvatarList : public LLFlatListView
 		Optional<bool> show_last_interaction_time; // show most recent interaction time. *HACK: move this to a derived class
 		Optional<bool> show_info_btn;
 		Optional<bool> show_profile_btn;
+		Optional<bool> show_speaking_indicator;
 		Params();
 	};
 
@@ -76,6 +77,7 @@ class LLAvatarList : public LLFlatListView
 	void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
 
 	void toggleIcons();
+	void setSpeakingIndicatorsVisible(bool visible);
 	void sortByName();
 	void setShowIcons(std::string param_name);
 	bool getIconsVisible() const { return mShowIcons; }
@@ -105,6 +107,7 @@ class LLAvatarList : public LLFlatListView
 	bool mShowIcons;
 	bool mShowInfoBtn;
 	bool mShowProfileBtn;
+	bool mShowSpeakingIndicator;
 
 	LLTimer*				mLITUpdateTimer; // last interaction time update timer
 	std::string				mIconParamName;
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index a7ac14c94862be1ce621247c6bbfd07fed892a7c..7df278d887bf6815d3a17926c3af569eef3a464a 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -62,6 +62,7 @@ LLAvatarListItem::LLAvatarListItem()
 	mIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
 	mInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight;
 	mProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight;
+	mSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight; 
 }
 
 LLAvatarListItem::~LLAvatarListItem()
@@ -230,6 +231,18 @@ void LLAvatarListItem::setShowProfileBtn(bool show)
 	mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
 }
 
+void LLAvatarListItem::setSpeakingIndicatorVisible(bool visible)
+{
+	// Already done? Then do nothing.
+	if (mSpeakingIndicator->getVisible() == (BOOL)visible)
+		return;
+	mSpeakingIndicator->setVisible(visible);
+	S32 width_delta = visible ? - mSpeakingIndicatorWidth : mSpeakingIndicatorWidth;
+
+	//Reshaping avatar name
+	mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
+}
+
 void LLAvatarListItem::setAvatarIconVisible(bool visible)
 {
 	// Already done? Then do nothing.
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index cd7a85c3dc5b4ca746df79c05067e027863b902d..d379797a464b8c47206709640e39863d76ca086f 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -65,8 +65,9 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
 	void setLastInteractionTime(const std::string& val);
 	//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
-	void setShowProfileBtn(bool hide);
-	void setShowInfoBtn(bool hide);
+	void setShowProfileBtn(bool show);
+	void setShowInfoBtn(bool show);
+	void setSpeakingIndicatorVisible(bool visible);
 	void setAvatarIconVisible(bool visible);
 	
 	const LLUUID& getAvatarId() const;
@@ -109,6 +110,7 @@ class LLAvatarListItem : public LLPanel, public LLFriendObserver
 	S32	 mIconWidth; // icon width + padding
 	S32  mInfoBtnWidth; //info btn width + padding
 	S32  mProfileBtnWidth; //profile btn width + padding
+	S32  mSpeakingIndicatorWidth; //speaking indicator width + padding
 };
 
 #endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 21e88b6d07c1f81a616d75a4e2aaa8c4ddde3635..80b29c4fa79fb8d5a847e001b3ee5573ad239f76 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -59,6 +59,14 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
 	// TODO: implement Voice Control Panel opening
 }
 
+void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+	bool is_call_started = ( new_state >= LLVoiceChannel::STATE_CALL_STARTED );
+	childSetVisible("end_call_btn", is_call_started);
+	childSetVisible("voice_ctrls_btn", is_call_started);
+	childSetVisible("call_btn", ! is_call_started);
+}
+
 BOOL LLPanelChatControlPanel::postBuild()
 {
 	childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
@@ -76,15 +84,6 @@ void LLPanelChatControlPanel::draw()
 	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
 	if (!session) return;
 
-	LLVoiceChannel* voice_channel = session->mVoiceChannel;
-	if (voice_channel && voice_enabled)
-	{
-		bool is_call_started = ( voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED );
-		childSetVisible("end_call_btn", is_call_started);
-		childSetVisible("voice_ctrls_btn", is_call_started);
-		childSetVisible("call_btn", ! is_call_started);
-	}
-
 	bool session_initialized = session->mSessionInitialized;
 	bool callback_enabled = session->mCallBackEnabled;
 	LLViewerRegion* region = gAgent.getRegion();
@@ -98,6 +97,15 @@ void LLPanelChatControlPanel::draw()
 	LLPanel::draw();
 }
 
+void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
+{
+	//Method is called twice for AdHoc and Group chat. Second time when server init reply received
+	mSessionId = session_id;
+	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId);
+	if(voice_channel)
+		voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
+}
+
 LLPanelIMControlPanel::LLPanelIMControlPanel()
 {
 }
@@ -214,6 +222,12 @@ void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata)
 
 }
 
+void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+	LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state);
+	mAvatarList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+}
+
 void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
 {
 	LLPanelChatControlPanel::setSessionId(session_id);
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index fa101f42803e636289f82dff9b5b21c6c5197222..1f38bffb538a95848a6f2a4e75719d66384406ff 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -34,6 +34,7 @@
 #define LL_LLPANELIMCONTROLPANEL_H
 
 #include "llpanel.h"
+#include "llvoicechannel.h"
 
 class LLSpeakerMgr;
 class LLAvatarList;
@@ -52,7 +53,9 @@ class LLPanelChatControlPanel : public LLPanel
 	void onEndCallButtonClicked();
 	void onOpenVoiceControlsClicked();
 
-	virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; }
+	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
+
+	virtual void setSessionId(const LLUUID& session_id);
 
 private:
 	LLUUID mSessionId;
@@ -100,6 +103,7 @@ class LLPanelGroupControlPanel : public LLPanelChatControlPanel
 private:
 	void onGroupInfoButtonClicked();
 	void onSortMenuItemClicked(const LLSD& userdata);
+	/*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
 };
 
 class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 96fcf61e62899c2b41bce022335a8eb435f3e531..cefc88ebee85249ec4bda34b0d70d113de31d4a6 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -390,7 +390,15 @@ void LLVoiceChannel::setState(EState state)
 		break;
 	}
 
-	mState = state;
+	doSetState(state);
+}
+
+void LLVoiceChannel::doSetState(const EState& new_state)
+{
+	EState old_state = mState;
+	mState = new_state;
+	if (!mStateChangedCallback.empty())
+		mStateChangedCallback(old_state, mState);
 }
 
 void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
@@ -620,7 +628,7 @@ void LLVoiceChannelGroup::setState(EState state)
 			gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
 		}
 
-		mState = state;
+		doSetState(state);
 		break;
 	default:
 		LLVoiceChannel::setState(state);
@@ -865,7 +873,7 @@ void LLVoiceChannelP2P::setState(EState state)
 	if (mReceivedCall && state == STATE_RINGING)
 	{
 		gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
-		mState = state;
+		doSetState(state);
 		return;
 	}
 	LLVoiceChannel::setState(state);
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 9966bdd5abff75798ab693808e037dae5196801b..8f1e9ff02d3c9807781b2e19425e408f2212440e 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -52,6 +52,8 @@ class LLVoiceChannel : public LLVoiceClientStatusObserver
 		STATE_CONNECTED
 	} EState;
 
+	typedef boost::function<void(const EState& old_state, const EState& new_state)> state_changed_callback_t;
+
 	LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
 	virtual ~LLVoiceChannel();
 
@@ -69,6 +71,8 @@ class LLVoiceChannel : public LLVoiceClientStatusObserver
 	virtual BOOL callStarted();
 	const std::string& getSessionName() const { return mSessionName; }
 
+	void setStateChangedCallback(state_changed_callback_t callback) { mStateChangedCallback = callback; }
+
 	const LLUUID getSessionID() { return mSessionID; }
 	EState getState() { return mState; }
 
@@ -85,6 +89,10 @@ class LLVoiceChannel : public LLVoiceClientStatusObserver
 
 protected:
 	virtual void setState(EState state);
+	/**
+	 * Use this method if you want mStateChangedCallback to be executed while state is changed
+	 */
+	void doSetState(const EState& state);
 	void toggleCallWindowIfNeeded(EState state);
 	void setURI(std::string uri);
 
@@ -106,6 +114,9 @@ class LLVoiceChannel : public LLVoiceClientStatusObserver
 	static LLVoiceChannel* sCurrentVoiceChannel;
 	static LLVoiceChannel* sSuspendedVoiceChannel;
 	static BOOL sSuspended;
+
+private:
+	state_changed_callback_t mStateChangedCallback;
 };
 
 class LLVoiceChannelGroup : public LLVoiceChannel
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
index 24c46b314ffa1832ce5f8e3f79966af7487733fd..0246e21d254d83bf6a69e9331c8b07310bb053b4 100644
--- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -16,6 +16,7 @@
      opaque="false"
      show_info_btn="false"
      show_profile_btn="false"
+     show_speaking_indicator="false"
      top="10"
      width="180"/>
 
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 46f34949a83c46f09ecde1bae5957fb35f391774..763dd7b922055ac2aa41c6bebc22e829e836cc65 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
@@ -16,6 +16,7 @@
      opaque="false"
      show_info_btn="false"
      show_profile_btn="false"
+     show_speaking_indicator="false"
      top="10"
      width="180"/>