PageRenderTime 104ms CodeModel.GetById 40ms app.highlight 20ms RepoModel.GetById 40ms app.codeStats 0ms

/indra/newview/lloutputmonitorctrl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 321 lines | 166 code | 37 blank | 118 comment | 31 complexity | 865fd8c3ab95df93be1a466bb03acdb9 MD5 | raw file
  1/** 
  2 * @file lloutputmonitorctrl.cpp
  3 * @brief LLOutputMonitorCtrl base class
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28#include "lloutputmonitorctrl.h"
 29
 30// library includes 
 31#include "llui.h"
 32
 33// viewer includes
 34#include "llvoiceclient.h"
 35#include "llmutelist.h"
 36#include "llagent.h"
 37
 38// default options set in output_monitor.xml
 39static LLDefaultChildRegistry::Register<LLOutputMonitorCtrl> r("output_monitor");
 40
 41// The defaults will be initialized in the constructor.
 42//LLColor4	LLOutputMonitorCtrl::sColorMuted;
 43//LLColor4	LLOutputMonitorCtrl::sColorOverdriven;
 44//LLColor4	LLOutputMonitorCtrl::sColorNormal;
 45LLColor4	LLOutputMonitorCtrl::sColorBound;
 46//S32			LLOutputMonitorCtrl::sRectsNumber 		= 0;
 47//F32			LLOutputMonitorCtrl::sRectWidthRatio	= 0.f;
 48//F32			LLOutputMonitorCtrl::sRectHeightRatio	= 0.f;
 49
 50LLOutputMonitorCtrl::Params::Params()
 51:	draw_border("draw_border"),
 52	image_mute("image_mute"),
 53	image_off("image_off"),
 54	image_on("image_on"),
 55	image_level_1("image_level_1"),
 56	image_level_2("image_level_2"),
 57	image_level_3("image_level_3"),
 58	auto_update("auto_update"),
 59	speaker_id("speaker_id")
 60{
 61};
 62
 63LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p)
 64:	LLView(p),
 65	mPower(0),
 66	mImageMute(p.image_mute),
 67	mImageOff(p.image_off),
 68	mImageOn(p.image_on),
 69	mImageLevel1(p.image_level_1),
 70	mImageLevel2(p.image_level_2),
 71	mImageLevel3(p.image_level_3),
 72	mAutoUpdate(p.auto_update),
 73	mSpeakerId(p.speaker_id),
 74	mIsAgentControl(false),
 75	mIsSwitchDirty(false),
 76	mShouldSwitchOn(false)
 77{
 78	//static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange);
 79	//static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red);
 80	//static LLUIColor output_monitor_normal_color = LLUIColorTable::instance().getColor("OutputMonitorNotmalColor", LLColor4::green);
 81	static LLUIColor output_monitor_bound_color = LLUIColorTable::instance().getColor("OutputMonitorBoundColor", LLColor4::white);
 82	//static LLUICachedControl<S32> output_monitor_rects_number("OutputMonitorRectanglesNumber", 20);
 83	//static LLUICachedControl<F32> output_monitor_rect_width_ratio("OutputMonitorRectangleWidthRatio", 0.5f);
 84	//static LLUICachedControl<F32> output_monitor_rect_height_ratio("OutputMonitorRectangleHeightRatio", 0.8f);
 85
 86	// IAN BUG compare to existing pattern where these are members - some will change per-widget and need to be anyway
 87	// sent feedback to PE
 88	
 89	// *TODO: it looks suboptimal to load the defaults every time an output monitor is constructed.
 90	//sColorMuted			= output_monitor_muted_color;
 91	//sColorOverdriven	= output_monitor_overdriven_color;
 92	//sColorNormal		= output_monitor_normal_color;
 93	sColorBound			= output_monitor_bound_color;
 94	//sRectsNumber		= output_monitor_rects_number;
 95	//sRectWidthRatio		= output_monitor_rect_width_ratio;
 96	//sRectHeightRatio	= output_monitor_rect_height_ratio;
 97
 98	mBorder = p.draw_border;
 99
100	//with checking mute state
101	setSpeakerId(mSpeakerId);
102}
103
104LLOutputMonitorCtrl::~LLOutputMonitorCtrl()
105{
106	LLMuteList::getInstance()->removeObserver(this);
107	LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this);
108}
109
110void LLOutputMonitorCtrl::setPower(F32 val)
111{
112	mPower = llmax(0.f, llmin(1.f, val));
113}
114
115void LLOutputMonitorCtrl::draw()
116{
117	// see also switchIndicator()
118	if (mIsSwitchDirty)
119	{
120		mIsSwitchDirty = false;
121		if (mShouldSwitchOn)
122		{
123			// just notify parent visibility may have changed
124			notifyParentVisibilityChanged();
125		}
126		else
127		{
128			// make itself invisible and notify parent about this
129			setVisible(FALSE);
130			notifyParentVisibilityChanged();
131
132			// no needs to render for invisible element
133			return;
134		}
135	}
136
137	// Copied from llmediaremotectrl.cpp
138	// *TODO: Give the LLOutputMonitorCtrl an agent-id to monitor, then
139	// call directly into LLVoiceClient::getInstance() to ask if that agent-id is muted, is
140	// speaking, and what power.  This avoids duplicating data, which can get
141	// out of sync.
142	const F32 LEVEL_0 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL / 3.f;
143	const F32 LEVEL_1 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL * 2.f / 3.f;
144	const F32 LEVEL_2 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
145
146	if (getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull())
147	{
148		setPower(LLVoiceClient::getInstance()->getCurrentPower(mSpeakerId));
149		if(mIsAgentControl)
150		{
151			setIsTalking(LLVoiceClient::getInstance()->getUserPTTState());
152		}
153		else
154		{
155			setIsTalking(LLVoiceClient::getInstance()->getIsSpeaking(mSpeakerId));
156		}
157	}
158
159	LLPointer<LLUIImage> icon;
160	if (mIsMuted)
161	{
162		icon = mImageMute;
163	}
164	else if (mPower == 0.f && !mIsTalking)
165	{
166		// only show off if PTT is not engaged
167		icon = mImageOff;
168	}
169	else if (mPower < LEVEL_0)
170	{
171		// PTT is on, possibly with quiet background noise
172		icon = mImageOn;
173	}
174	else if (mPower < LEVEL_1)
175	{
176		icon = mImageLevel1;
177	}
178	else if (mPower < LEVEL_2)
179	{
180		icon = mImageLevel2;
181	}
182	else
183	{
184		// overdriven
185		icon = mImageLevel3;
186	}
187
188	if (icon)
189	{
190		icon->draw(0, 0);
191	}
192
193	//
194	// Fill the monitor with a bunch of small rectangles.
195	// The rectangles will be filled with gradient color,
196	// beginning with sColorNormal and ending with sColorOverdriven.
197	// 
198	// *TODO: would using a (partially drawn) pixmap instead be faster?
199	//
200	const int monh		= getRect().getHeight();
201	const int monw		= getRect().getWidth();
202	//int maxrects		= sRectsNumber;
203	//const int period	= llmax(1, monw / maxrects, 0, 0);                    // "1" - min value for the period
204	//const int rectw		= llmax(1, llfloor(period * sRectWidthRatio), 0, 0);  // "1" - min value for the rect's width
205	//const int recth		= llfloor(monh * sRectHeightRatio);
206
207	//if(period == 1 && rectw == 1) //if we have so small control, then "maxrects = monitor's_width - 2*monitor_border's_width
208	//	maxrects = monw-2;
209
210	//const int nrects	= mIsMuted ? maxrects : llfloor(mPower * maxrects); // how many rects to draw?
211	//const int rectbtm	= (monh - recth) / 2;
212	//const int recttop	= rectbtm + recth;
213	//
214	//LLColor4 rect_color;
215	//
216	//for (int i=1, xpos = 0; i <= nrects; i++)
217	//{
218	//	// Calculate color to use for the current rectangle.
219	//	if (mIsMuted)
220	//	{
221	//		rect_color = sColorMuted;
222	//	}
223	//	else
224	//	{
225	//		F32 frac = (mPower * i/nrects) / LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
226	//		// Use overdriven color if the power exceeds overdriven level.
227	//		if (frac > 1.0f)
228	//			frac = 1.0f;
229	//		rect_color = lerp(sColorNormal, sColorOverdriven, frac);
230	//	}
231
232	//	// Draw rectangle filled with the color.
233	//	gl_rect_2d(xpos, recttop, xpos+rectw, rectbtm, rect_color, TRUE);
234	//	xpos += period;
235	//}
236
237	//
238	// Draw bounding box.
239	//
240	if(mBorder)
241		gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE);
242}
243
244void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/)
245{
246	if (speaker_id.isNull() && mSpeakerId.notNull())
247	{
248		LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this);
249	}
250
251	if (speaker_id.isNull() || speaker_id == mSpeakerId) return;
252
253	if (mSpeakerId.notNull())
254	{
255		// Unregister previous registration to avoid crash. EXT-4782.
256		LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this);
257	}
258
259	mSpeakerId = speaker_id;
260	LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id);
261
262	//mute management
263	if (mAutoUpdate)
264	{
265		if (speaker_id == gAgentID)
266		{
267			setIsMuted(false);
268		}
269		else
270		{
271			// check only blocking on voice. EXT-3542
272			setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat));
273			LLMuteList::getInstance()->addObserver(this);
274		}
275	}
276}
277
278void LLOutputMonitorCtrl::onChange()
279{
280	// check only blocking on voice. EXT-3542
281	setIsMuted(LLMuteList::getInstance()->isMuted(mSpeakerId, LLMute::flagVoiceChat));
282}
283
284// virtual
285void LLOutputMonitorCtrl::switchIndicator(bool switch_on)
286{
287	// ensure indicator is visible in case it is not in visible chain
288	// to be called when parent became visible next time to notify parent that visibility is changed.
289	setVisible(TRUE);
290
291	// if parent is in visible chain apply switch_on state and notify it immediately
292	if (getParent() && getParent()->isInVisibleChain())
293	{
294		LL_DEBUGS("SpeakingIndicator") << "Indicator is in visible chain, notifying parent: " << mSpeakerId << LL_ENDL;
295		setVisible((BOOL)switch_on);
296		notifyParentVisibilityChanged();
297	}
298
299	// otherwise remember necessary state and mark itself as dirty.
300	// State will be applied in next draw when parents chain becomes visible.
301	else
302	{
303		LL_DEBUGS("SpeakingIndicator") << "Indicator is not in visible chain, parent won't be notified: " << mSpeakerId << LL_ENDL;
304		mIsSwitchDirty = true;
305		mShouldSwitchOn = switch_on;
306	}
307}
308
309//////////////////////////////////////////////////////////////////////////
310// PRIVATE SECTION
311//////////////////////////////////////////////////////////////////////////
312void LLOutputMonitorCtrl::notifyParentVisibilityChanged()
313{
314	LL_DEBUGS("SpeakingIndicator") << "Notify parent that visibility was changed: " << mSpeakerId << ", new_visibility: " << getVisible() << LL_ENDL;
315
316	LLSD params = LLSD().with("visibility_changed", getVisible());
317
318	notifyParent(params);
319}
320
321// EOF