diff options
author | Jacek Antonelli | 2008-08-15 23:45:27 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:27 -0500 |
commit | a8a62201ba762e98dff92cf49033e577fc34d8d4 (patch) | |
tree | 11f8513c5cdc222f2fac0c93eb724c089803c200 /linden/indra/newview/llfloateractivespeakers.cpp | |
parent | Second Life viewer sources 1.18.6.4-RC (diff) | |
download | meta-impy-a8a62201ba762e98dff92cf49033e577fc34d8d4.zip meta-impy-a8a62201ba762e98dff92cf49033e577fc34d8d4.tar.gz meta-impy-a8a62201ba762e98dff92cf49033e577fc34d8d4.tar.bz2 meta-impy-a8a62201ba762e98dff92cf49033e577fc34d8d4.tar.xz |
Second Life viewer sources 1.19.0.0
Diffstat (limited to 'linden/indra/newview/llfloateractivespeakers.cpp')
-rw-r--r-- | linden/indra/newview/llfloateractivespeakers.cpp | 563 |
1 files changed, 504 insertions, 59 deletions
diff --git a/linden/indra/newview/llfloateractivespeakers.cpp b/linden/indra/newview/llfloateractivespeakers.cpp index fb50717..877ebca 100644 --- a/linden/indra/newview/llfloateractivespeakers.cpp +++ b/linden/indra/newview/llfloateractivespeakers.cpp | |||
@@ -12,12 +12,12 @@ | |||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | 12 | * ("GPL"), unless you have obtained a separate licensing agreement |
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | 13 | * ("Other License"), formally executed by you and Linden Lab. Terms of |
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | 14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or |
15 | * online at http://secondlife.com/developers/opensource/gplv2 | 15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 |
16 | * | 16 | * |
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlife.com/developers/opensource/flossexception | 20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception |
21 | * | 21 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 22 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 23 | * that you have read and understood your obligations described above, |
@@ -45,6 +45,7 @@ | |||
45 | #include "llviewerobjectlist.h" | 45 | #include "llviewerobjectlist.h" |
46 | #include "llimpanel.h" // LLVoiceChannel | 46 | #include "llimpanel.h" // LLVoiceChannel |
47 | #include "llsdutil.h" | 47 | #include "llsdutil.h" |
48 | #include "llimview.h" | ||
48 | 49 | ||
49 | const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers | 50 | const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers |
50 | const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); | 51 | const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); |
@@ -65,7 +66,10 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const LLString& name, const ESpeakerType | |||
65 | mID(id), | 66 | mID(id), |
66 | mTyping(FALSE), | 67 | mTyping(FALSE), |
67 | mSortIndex(0), | 68 | mSortIndex(0), |
68 | mType(type) | 69 | mType(type), |
70 | mIsModerator(FALSE), | ||
71 | mModeratorMutedVoice(FALSE), | ||
72 | mModeratorMutedText(FALSE) | ||
69 | { | 73 | { |
70 | mHandle.init(); | 74 | mHandle.init(); |
71 | sSpeakers.insert(std::make_pair(mHandle, this)); | 75 | sSpeakers.insert(std::make_pair(mHandle, this)); |
@@ -77,6 +81,9 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const LLString& name, const ESpeakerType | |||
77 | { | 81 | { |
78 | mDisplayName = name; | 82 | mDisplayName = name; |
79 | } | 83 | } |
84 | |||
85 | gVoiceClient->setUserVolume(id, gMuteListp->getSavedResidentVolume(id)); | ||
86 | |||
80 | mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); | 87 | mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); |
81 | } | 88 | } |
82 | 89 | ||
@@ -107,6 +114,27 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const char* first, const ch | |||
107 | } | 114 | } |
108 | } | 115 | } |
109 | 116 | ||
117 | LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source) | ||
118 | : LLEvent(source, "Speaker text moderation event") | ||
119 | { | ||
120 | } | ||
121 | |||
122 | LLSD LLSpeakerTextModerationEvent::getValue() | ||
123 | { | ||
124 | return LLString("text"); | ||
125 | } | ||
126 | |||
127 | |||
128 | LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source) | ||
129 | : LLEvent(source, "Speaker voice moderation event") | ||
130 | { | ||
131 | } | ||
132 | |||
133 | LLSD LLSpeakerVoiceModerationEvent::getValue() | ||
134 | { | ||
135 | return LLString("voice"); | ||
136 | } | ||
137 | |||
110 | 138 | ||
111 | // helper sort class | 139 | // helper sort class |
112 | struct LLSortRecentSpeakers | 140 | struct LLSortRecentSpeakers |
@@ -132,6 +160,10 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo | |||
132 | return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 ); | 160 | return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 ); |
133 | } | 161 | } |
134 | 162 | ||
163 | // | ||
164 | // LLFloaterActiveSpeakers | ||
165 | // | ||
166 | |||
135 | LLFloaterActiveSpeakers::LLFloaterActiveSpeakers(const LLSD& seed) : mPanel(NULL) | 167 | LLFloaterActiveSpeakers::LLFloaterActiveSpeakers(const LLSD& seed) : mPanel(NULL) |
136 | { | 168 | { |
137 | mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL); | 169 | mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL); |
@@ -177,6 +209,26 @@ void* LLFloaterActiveSpeakers::createSpeakersPanel(void* data) | |||
177 | return new LLPanelActiveSpeakers(gActiveChannelSpeakerMgr, FALSE); | 209 | return new LLPanelActiveSpeakers(gActiveChannelSpeakerMgr, FALSE); |
178 | } | 210 | } |
179 | 211 | ||
212 | // | ||
213 | // LLPanelActiveSpeakers::LLSpeakerListener | ||
214 | // | ||
215 | bool LLPanelActiveSpeakers::LLSpeakerListener::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
216 | { | ||
217 | LLPointer<LLSpeaker> speakerp = (LLSpeaker*)event->getSource(); | ||
218 | if (speakerp.isNull()) return false; | ||
219 | |||
220 | // update UI on confirmation of moderator mutes | ||
221 | if (event->getValue().asString() == "voice") | ||
222 | { | ||
223 | mPanel->childSetValue("moderator_allow_voice", !speakerp->mModeratorMutedVoice); | ||
224 | } | ||
225 | if (event->getValue().asString() == "text") | ||
226 | { | ||
227 | mPanel->childSetValue("moderator_allow_text", !speakerp->mModeratorMutedText); | ||
228 | } | ||
229 | return true; | ||
230 | } | ||
231 | |||
180 | 232 | ||
181 | // | 233 | // |
182 | // LLPanelActiveSpeakers | 234 | // LLPanelActiveSpeakers |
@@ -191,6 +243,7 @@ LLPanelActiveSpeakers::LLPanelActiveSpeakers(LLSpeakerMgr* data_source, BOOL sho | |||
191 | mSpeakerMgr(data_source) | 243 | mSpeakerMgr(data_source) |
192 | { | 244 | { |
193 | setMouseOpaque(FALSE); | 245 | setMouseOpaque(FALSE); |
246 | mSpeakerListener = new LLSpeakerListener(this); | ||
194 | } | 247 | } |
195 | 248 | ||
196 | LLPanelActiveSpeakers::~LLPanelActiveSpeakers() | 249 | LLPanelActiveSpeakers::~LLPanelActiveSpeakers() |
@@ -201,6 +254,10 @@ LLPanelActiveSpeakers::~LLPanelActiveSpeakers() | |||
201 | BOOL LLPanelActiveSpeakers::postBuild() | 254 | BOOL LLPanelActiveSpeakers::postBuild() |
202 | { | 255 | { |
203 | mSpeakerList = LLUICtrlFactory::getScrollListByName(this, "speakers_list"); | 256 | mSpeakerList = LLUICtrlFactory::getScrollListByName(this, "speakers_list"); |
257 | mSpeakerList->setDoubleClickCallback(onDoubleClickSpeaker); | ||
258 | mSpeakerList->setCommitOnSelectionChange(TRUE); | ||
259 | mSpeakerList->setCommitCallback(onSelectSpeaker); | ||
260 | mSpeakerList->setCallbackUserData(this); | ||
204 | 261 | ||
205 | mMuteTextCtrl = (LLUICtrl*)getCtrlByNameAndType("mute_text_btn", WIDGET_TYPE_DONTCARE); | 262 | mMuteTextCtrl = (LLUICtrl*)getCtrlByNameAndType("mute_text_btn", WIDGET_TYPE_DONTCARE); |
206 | childSetCommitCallback("mute_text_btn", onClickMuteTextCommit, this); | 263 | childSetCommitCallback("mute_text_btn", onClickMuteTextCommit, this); |
@@ -215,13 +272,39 @@ BOOL LLPanelActiveSpeakers::postBuild() | |||
215 | 272 | ||
216 | mProfileBtn = LLUICtrlFactory::getButtonByName(this, "profile_btn"); | 273 | mProfileBtn = LLUICtrlFactory::getButtonByName(this, "profile_btn"); |
217 | childSetAction("profile_btn", onClickProfile, this); | 274 | childSetAction("profile_btn", onClickProfile, this); |
275 | |||
276 | childSetCommitCallback("moderator_allow_voice", onModeratorMuteVoice, this); | ||
277 | childSetCommitCallback("moderator_allow_text", onModeratorMuteText, this); | ||
278 | childSetCommitCallback("moderation_mode", onChangeModerationMode, this); | ||
279 | |||
280 | // update speaker UI | ||
281 | handleSpeakerSelect(); | ||
282 | |||
218 | return TRUE; | 283 | return TRUE; |
219 | } | 284 | } |
220 | 285 | ||
286 | void LLPanelActiveSpeakers::handleSpeakerSelect() | ||
287 | { | ||
288 | LLUUID speaker_id = mSpeakerList->getValue().asUUID(); | ||
289 | LLPointer<LLSpeaker> selected_speakerp = mSpeakerMgr->findSpeaker(speaker_id); | ||
290 | |||
291 | if (selected_speakerp.notNull()) | ||
292 | { | ||
293 | // since setting these values is delayed by a round trip to the Vivox servers | ||
294 | // update them only when selecting a new speaker or | ||
295 | // asynchronously when an update arrives | ||
296 | childSetValue("moderator_allow_voice", selected_speakerp ? !selected_speakerp->mModeratorMutedVoice : TRUE); | ||
297 | childSetValue("moderator_allow_text", selected_speakerp ? !selected_speakerp->mModeratorMutedText : TRUE); | ||
298 | |||
299 | mSpeakerListener->clearDispatchers(); | ||
300 | selected_speakerp->addListener(mSpeakerListener); | ||
301 | } | ||
302 | } | ||
303 | |||
221 | void LLPanelActiveSpeakers::refreshSpeakers() | 304 | void LLPanelActiveSpeakers::refreshSpeakers() |
222 | { | 305 | { |
223 | // store off current selection and scroll state to preserve across list rebuilds | 306 | // store off current selection and scroll state to preserve across list rebuilds |
224 | LLUUID selected_id = mSpeakerList->getSimpleSelectedValue().asUUID(); | 307 | LLUUID selected_id = mSpeakerList->getSelectedValue().asUUID(); |
225 | S32 scroll_pos = mSpeakerList->getScrollInterface()->getScrollPos(); | 308 | S32 scroll_pos = mSpeakerList->getScrollInterface()->getScrollPos(); |
226 | 309 | ||
227 | BOOL sort_ascending = mSpeakerList->getSortAscending(); | 310 | BOOL sort_ascending = mSpeakerList->getSortAscending(); |
@@ -253,7 +336,6 @@ void LLPanelActiveSpeakers::refreshSpeakers() | |||
253 | 336 | ||
254 | row["columns"][0]["column"] = "icon_speaking_status"; | 337 | row["columns"][0]["column"] = "icon_speaking_status"; |
255 | row["columns"][0]["type"] = "icon"; | 338 | row["columns"][0]["type"] = "icon"; |
256 | row["columns"][0]["color"] = speakerp->mDotColor.getValue(); | ||
257 | LLString icon_image_id; | 339 | LLString icon_image_id; |
258 | 340 | ||
259 | S32 icon_image_idx = llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); | 341 | S32 icon_image_idx = llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); |
@@ -288,8 +370,33 @@ void LLPanelActiveSpeakers::refreshSpeakers() | |||
288 | // } | 370 | // } |
289 | //} | 371 | //} |
290 | 372 | ||
291 | row["columns"][0]["value"] = (speakerp->mStatus == LLSpeaker::STATUS_MUTED) ? | 373 | LLColor4 icon_color; |
292 | gViewerArt.getString("mute_icon.tga") : icon_image_id; | 374 | if (speakerp->mStatus == LLSpeaker::STATUS_MUTED) |
375 | { | ||
376 | row["columns"][0]["value"] = gViewerArt.getString("mute_icon.tga"); | ||
377 | if(speakerp->mModeratorMutedVoice) | ||
378 | { | ||
379 | icon_color.setVec(0.5f, 0.5f, 0.5f, 1.f); | ||
380 | } | ||
381 | else | ||
382 | { | ||
383 | icon_color.setVec(1.f, 71.f / 255.f, 71.f / 255.f, 1.f); | ||
384 | } | ||
385 | } | ||
386 | else | ||
387 | { | ||
388 | row["columns"][0]["value"] = icon_image_id; | ||
389 | icon_color = speakerp->mDotColor; | ||
390 | |||
391 | if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE) // if voice is disabled for this speaker | ||
392 | { | ||
393 | // non voice speakers have hidden icons, render as transparent | ||
394 | icon_color.setVec(0.f, 0.f, 0.f, 0.f); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | row["columns"][0]["color"] = icon_color.getValue(); | ||
399 | |||
293 | if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE && speakerp->mStatus != LLSpeaker::STATUS_MUTED) // if voice is disabled for this speaker | 400 | if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE && speakerp->mStatus != LLSpeaker::STATUS_MUTED) // if voice is disabled for this speaker |
294 | { | 401 | { |
295 | // non voice speakers have hidden icons, render as transparent | 402 | // non voice speakers have hidden icons, render as transparent |
@@ -303,15 +410,23 @@ void LLPanelActiveSpeakers::refreshSpeakers() | |||
303 | row["columns"][1]["color"] = LLColor4::grey4.getValue(); | 410 | row["columns"][1]["color"] = LLColor4::grey4.getValue(); |
304 | } | 411 | } |
305 | 412 | ||
413 | LLString speaker_name; | ||
306 | if (speakerp->mDisplayName.empty()) | 414 | if (speakerp->mDisplayName.empty()) |
307 | { | 415 | { |
308 | row["columns"][1]["value"] = LLCacheName::getDefaultName(); | 416 | speaker_name = LLCacheName::getDefaultName(); |
309 | } | 417 | } |
310 | else | 418 | else |
311 | { | 419 | { |
312 | row["columns"][1]["value"] = speakerp->mDisplayName; | 420 | speaker_name = speakerp->mDisplayName; |
313 | } | 421 | } |
314 | 422 | ||
423 | if (speakerp->mIsModerator) | ||
424 | { | ||
425 | speaker_name += LLString(" ") + getFormattedUIString("moderator_label"); | ||
426 | } | ||
427 | row["columns"][1]["value"] = speaker_name; | ||
428 | row["columns"][1]["font-style"] = speakerp->mIsModerator ? "BOLD" : "NORMAL"; | ||
429 | |||
315 | row["columns"][2]["column"] = "speaking_status"; | 430 | row["columns"][2]["column"] = "speaking_status"; |
316 | row["columns"][2]["type"] = "text"; | 431 | row["columns"][2]["type"] = "text"; |
317 | 432 | ||
@@ -323,17 +438,28 @@ void LLPanelActiveSpeakers::refreshSpeakers() | |||
323 | 438 | ||
324 | //restore sort order, selection, etc | 439 | //restore sort order, selection, etc |
325 | mSpeakerList->sortByColumn(sort_column, sort_ascending); | 440 | mSpeakerList->sortByColumn(sort_column, sort_ascending); |
441 | |||
442 | // temporarily disable commit callback while restoring original selection | ||
443 | mSpeakerList->setCommitCallback(NULL); | ||
444 | |||
326 | // make sure something is selected | 445 | // make sure something is selected |
327 | if (selected_id.isNull()) | 446 | if (selected_id.isNull()) |
328 | { | 447 | { |
329 | mSpeakerList->selectFirstItem(); | 448 | mSpeakerList->selectFirstItem(); |
449 | handleSpeakerSelect(); | ||
330 | } | 450 | } |
331 | else | 451 | else |
332 | { | 452 | { |
453 | // reselect original speaker but don't call handleSpeakerSelect() | ||
454 | // as that would change the moderation mute checkboxes before they | ||
455 | // have had time to get confirmation from the server | ||
333 | mSpeakerList->selectByValue(selected_id); | 456 | mSpeakerList->selectByValue(selected_id); |
334 | } | 457 | } |
335 | 458 | ||
336 | LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(selected_id); | 459 | mSpeakerList->setCommitCallback(onSelectSpeaker); |
460 | |||
461 | LLPointer<LLSpeaker> selected_speakerp = mSpeakerMgr->findSpeaker(selected_id); | ||
462 | |||
337 | 463 | ||
338 | if (gMuteListp) | 464 | if (gMuteListp) |
339 | { | 465 | { |
@@ -341,31 +467,53 @@ void LLPanelActiveSpeakers::refreshSpeakers() | |||
341 | if (mMuteVoiceCtrl) | 467 | if (mMuteVoiceCtrl) |
342 | { | 468 | { |
343 | mMuteVoiceCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagVoiceChat)); | 469 | mMuteVoiceCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagVoiceChat)); |
344 | mMuteVoiceCtrl->setEnabled(selected_id.notNull() | 470 | mMuteVoiceCtrl->setEnabled(LLVoiceClient::voiceEnabled() |
471 | && gVoiceClient->getVoiceEnabled(selected_id) | ||
472 | && selected_id.notNull() | ||
345 | && selected_id != gAgent.getID() | 473 | && selected_id != gAgent.getID() |
346 | && (speakerp.notNull() && speakerp->mType == LLSpeaker::SPEAKER_AGENT)); | 474 | && (selected_speakerp.notNull() && selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT)); |
347 | } | 475 | } |
348 | if (mMuteTextCtrl) | 476 | if (mMuteTextCtrl) |
349 | { | 477 | { |
350 | mMuteTextCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagTextChat)); | 478 | mMuteTextCtrl->setValue(gMuteListp->isMuted(selected_id, LLMute::flagTextChat)); |
351 | mMuteTextCtrl->setEnabled(selected_id.notNull() && selected_id != gAgent.getID() && speakerp.notNull() && !gMuteListp->isLinden(speakerp->mDisplayName)); | 479 | mMuteTextCtrl->setEnabled(selected_id.notNull() |
352 | } | 480 | && selected_id != gAgent.getID() |
353 | childSetValue("speaker_volume", gVoiceClient->getUserVolume(selected_id)); | 481 | && selected_speakerp.notNull() |
354 | childSetEnabled("speaker_volume", selected_id.notNull() | 482 | && !gMuteListp->isLinden(selected_speakerp->mDisplayName)); |
355 | && selected_id != gAgent.getID() | ||
356 | && (speakerp.notNull() && speakerp->mType == LLSpeaker::SPEAKER_AGENT)); | ||
357 | if (mProfileBtn) | ||
358 | { | ||
359 | mProfileBtn->setEnabled(selected_id.notNull()); | ||
360 | } | 483 | } |
361 | } | 484 | } |
485 | childSetValue("speaker_volume", gVoiceClient->getUserVolume(selected_id)); | ||
486 | childSetEnabled("speaker_volume", LLVoiceClient::voiceEnabled() | ||
487 | && gVoiceClient->getVoiceEnabled(selected_id) | ||
488 | && selected_id.notNull() | ||
489 | && selected_id != gAgent.getID() | ||
490 | && (selected_speakerp.notNull() && selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT)); | ||
491 | |||
492 | childSetEnabled( | ||
493 | "moderator_controls_label", | ||
494 | selected_id.notNull()); | ||
495 | |||
496 | childSetEnabled( | ||
497 | "moderator_allow_voice", | ||
498 | selected_id.notNull() | ||
499 | && mSpeakerMgr->isVoiceActive() | ||
500 | && gVoiceClient->getVoiceEnabled(selected_id)); | ||
501 | |||
502 | childSetEnabled( | ||
503 | "moderator_allow_text", | ||
504 | selected_id.notNull()); | ||
505 | |||
506 | if (mProfileBtn) | ||
507 | { | ||
508 | mProfileBtn->setEnabled(selected_id.notNull()); | ||
509 | } | ||
362 | 510 | ||
363 | // show selected user name in large font | 511 | // show selected user name in large font |
364 | if (mNameText) | 512 | if (mNameText) |
365 | { | 513 | { |
366 | if (speakerp) | 514 | if (selected_speakerp) |
367 | { | 515 | { |
368 | mNameText->setValue(speakerp->mDisplayName); | 516 | mNameText->setValue(selected_speakerp->mDisplayName); |
369 | } | 517 | } |
370 | else | 518 | else |
371 | { | 519 | { |
@@ -373,6 +521,14 @@ void LLPanelActiveSpeakers::refreshSpeakers() | |||
373 | } | 521 | } |
374 | } | 522 | } |
375 | 523 | ||
524 | //update moderator capabilities | ||
525 | LLPointer<LLSpeaker> self_speakerp = mSpeakerMgr->findSpeaker(gAgent.getID()); | ||
526 | if(self_speakerp) | ||
527 | { | ||
528 | childSetVisible("moderation_mode_panel", self_speakerp->mIsModerator && mSpeakerMgr->isVoiceActive()); | ||
529 | childSetVisible("moderator_controls", self_speakerp->mIsModerator); | ||
530 | } | ||
531 | |||
376 | // keep scroll value stable | 532 | // keep scroll value stable |
377 | mSpeakerList->getScrollInterface()->setScrollPos(scroll_pos); | 533 | mSpeakerList->getScrollInterface()->setScrollPos(scroll_pos); |
378 | } | 534 | } |
@@ -382,6 +538,20 @@ void LLPanelActiveSpeakers::setSpeaker(const LLUUID& id, const LLString& name, L | |||
382 | mSpeakerMgr->setSpeaker(id, name, status, type); | 538 | mSpeakerMgr->setSpeaker(id, name, status, type); |
383 | } | 539 | } |
384 | 540 | ||
541 | void LLPanelActiveSpeakers::setVoiceModerationCtrlMode( | ||
542 | const BOOL& moderated_voice) | ||
543 | { | ||
544 | LLUICtrl* voice_moderation_ctrl = (LLUICtrl*) getChildByName( | ||
545 | "moderation_mode", TRUE); //recursive lookup | ||
546 | |||
547 | if ( voice_moderation_ctrl ) | ||
548 | { | ||
549 | std::string value; | ||
550 | |||
551 | value = moderated_voice ? "moderated" : "unmoderated"; | ||
552 | voice_moderation_ctrl->setValue(value); | ||
553 | } | ||
554 | } | ||
385 | 555 | ||
386 | //static | 556 | //static |
387 | void LLPanelActiveSpeakers::onClickMuteTextCommit(LLUICtrl* ctrl, void* user_data) | 557 | void LLPanelActiveSpeakers::onClickMuteTextCommit(LLUICtrl* ctrl, void* user_data) |
@@ -454,7 +624,11 @@ void LLPanelActiveSpeakers::onVolumeChange(LLUICtrl* source, void* user_data) | |||
454 | LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; | 624 | LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; |
455 | LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); | 625 | LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); |
456 | 626 | ||
457 | gVoiceClient->setUserVolume(speaker_id, (F32)panelp->childGetValue("speaker_volume").asReal()); | 627 | F32 new_volume = (F32)panelp->childGetValue("speaker_volume").asReal(); |
628 | gVoiceClient->setUserVolume(speaker_id, new_volume); | ||
629 | |||
630 | // store this volume setting for future sessions | ||
631 | gMuteListp->setSavedResidentVolume(speaker_id, new_volume); | ||
458 | } | 632 | } |
459 | 633 | ||
460 | //static | 634 | //static |
@@ -465,7 +639,190 @@ void LLPanelActiveSpeakers::onClickProfile(void* user_data) | |||
465 | 639 | ||
466 | LLFloaterAvatarInfo::showFromDirectory(speaker_id); | 640 | LLFloaterAvatarInfo::showFromDirectory(speaker_id); |
467 | } | 641 | } |
468 | 642 | ||
643 | //static | ||
644 | void LLPanelActiveSpeakers::onDoubleClickSpeaker(void* user_data) | ||
645 | { | ||
646 | LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; | ||
647 | LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID(); | ||
648 | |||
649 | LLPointer<LLSpeaker> speakerp = panelp->mSpeakerMgr->findSpeaker(speaker_id); | ||
650 | |||
651 | if (speaker_id != gAgent.getID() && speakerp.notNull()) | ||
652 | { | ||
653 | gIMMgr->addSession(speakerp->mDisplayName, IM_NOTHING_SPECIAL, speaker_id); | ||
654 | } | ||
655 | } | ||
656 | |||
657 | //static | ||
658 | void LLPanelActiveSpeakers::onSelectSpeaker(LLUICtrl* source, void* user_data) | ||
659 | { | ||
660 | LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data; | ||
661 | panelp->handleSpeakerSelect(); | ||
662 | } | ||
663 | |||
664 | //static | ||
665 | void LLPanelActiveSpeakers::onModeratorMuteVoice(LLUICtrl* ctrl, void* user_data) | ||
666 | { | ||
667 | LLPanelActiveSpeakers* self = (LLPanelActiveSpeakers*)user_data; | ||
668 | LLUICtrl* speakers_list = (LLUICtrl*)self->getChildByName("speakers_list", TRUE); | ||
669 | if (!speakers_list || !gAgent.getRegion()) return; | ||
670 | |||
671 | std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); | ||
672 | LLSD data; | ||
673 | data["method"] = "mute update"; | ||
674 | data["session-id"] = self->mSpeakerMgr->getSessionID(); | ||
675 | data["params"] = LLSD::emptyMap(); | ||
676 | data["params"]["agent_id"] = speakers_list->getValue(); | ||
677 | data["params"]["mutes"] = LLSD::emptyMap(); | ||
678 | // ctrl value represents ability to type, so invert | ||
679 | data["params"]["mutes"]["voice"] = !ctrl->getValue(); | ||
680 | |||
681 | class MuteVoiceResponder : public LLHTTPClient::Responder | ||
682 | { | ||
683 | public: | ||
684 | MuteVoiceResponder(const LLUUID& session_id) | ||
685 | { | ||
686 | mSessionID = session_id; | ||
687 | } | ||
688 | |||
689 | virtual void error(U32 status, const std::string& reason) | ||
690 | { | ||
691 | llwarns << status << ": " << reason << llendl; | ||
692 | |||
693 | if ( gIMMgr ) | ||
694 | { | ||
695 | //403 == you're not a mod | ||
696 | //should be disabled if you're not a moderator | ||
697 | LLFloaterIMPanel* floaterp; | ||
698 | |||
699 | floaterp = gIMMgr->findFloaterBySession(mSessionID); | ||
700 | |||
701 | if ( floaterp ) | ||
702 | { | ||
703 | if ( 403 == status ) | ||
704 | { | ||
705 | floaterp->showSessionEventError( | ||
706 | "mute", | ||
707 | "not_a_moderator"); | ||
708 | } | ||
709 | else | ||
710 | { | ||
711 | floaterp->showSessionEventError( | ||
712 | "mute", | ||
713 | "generic"); | ||
714 | } | ||
715 | } | ||
716 | } | ||
717 | } | ||
718 | |||
719 | private: | ||
720 | LLUUID mSessionID; | ||
721 | }; | ||
722 | |||
723 | LLHTTPClient::post( | ||
724 | url, | ||
725 | data, | ||
726 | new MuteVoiceResponder(self->mSpeakerMgr->getSessionID())); | ||
727 | } | ||
728 | |||
729 | //static | ||
730 | void LLPanelActiveSpeakers::onModeratorMuteText(LLUICtrl* ctrl, void* user_data) | ||
731 | { | ||
732 | LLPanelActiveSpeakers* self = (LLPanelActiveSpeakers*)user_data; | ||
733 | LLUICtrl* speakers_list = (LLUICtrl*)self->getChildByName("speakers_list", TRUE); | ||
734 | if (!speakers_list || !gAgent.getRegion()) return; | ||
735 | |||
736 | std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); | ||
737 | LLSD data; | ||
738 | data["method"] = "mute update"; | ||
739 | data["session-id"] = self->mSpeakerMgr->getSessionID(); | ||
740 | data["params"] = LLSD::emptyMap(); | ||
741 | data["params"]["agent_id"] = speakers_list->getValue(); | ||
742 | data["params"]["mutes"] = LLSD::emptyMap(); | ||
743 | // ctrl value represents ability to type, so invert | ||
744 | data["params"]["mutes"]["text"] = !ctrl->getValue(); | ||
745 | |||
746 | class MuteTextResponder : public LLHTTPClient::Responder | ||
747 | { | ||
748 | public: | ||
749 | MuteTextResponder(const LLUUID& session_id) | ||
750 | { | ||
751 | mSessionID = session_id; | ||
752 | } | ||
753 | |||
754 | virtual void error(U32 status, const std::string& reason) | ||
755 | { | ||
756 | llwarns << status << ": " << reason << llendl; | ||
757 | |||
758 | if ( gIMMgr ) | ||
759 | { | ||
760 | //403 == you're not a mod | ||
761 | //should be disabled if you're not a moderator | ||
762 | LLFloaterIMPanel* floaterp; | ||
763 | |||
764 | floaterp = gIMMgr->findFloaterBySession(mSessionID); | ||
765 | |||
766 | if ( floaterp ) | ||
767 | { | ||
768 | if ( 403 == status ) | ||
769 | { | ||
770 | floaterp->showSessionEventError( | ||
771 | "mute", | ||
772 | "not_a_moderator"); | ||
773 | } | ||
774 | else | ||
775 | { | ||
776 | floaterp->showSessionEventError( | ||
777 | "mute", | ||
778 | "generic"); | ||
779 | } | ||
780 | } | ||
781 | } | ||
782 | } | ||
783 | |||
784 | private: | ||
785 | LLUUID mSessionID; | ||
786 | }; | ||
787 | |||
788 | LLHTTPClient::post( | ||
789 | url, | ||
790 | data, | ||
791 | new MuteTextResponder(self->mSpeakerMgr->getSessionID())); | ||
792 | } | ||
793 | |||
794 | //static | ||
795 | void LLPanelActiveSpeakers::onChangeModerationMode(LLUICtrl* ctrl, void* user_data) | ||
796 | { | ||
797 | LLPanelActiveSpeakers* self = (LLPanelActiveSpeakers*)user_data; | ||
798 | if (!gAgent.getRegion()) return; | ||
799 | |||
800 | std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); | ||
801 | LLSD data; | ||
802 | data["method"] = "session update"; | ||
803 | data["session-id"] = self->mSpeakerMgr->getSessionID(); | ||
804 | data["params"] = LLSD::emptyMap(); | ||
805 | data["params"]["moderated_mode"] = LLSD::emptyMap(); | ||
806 | if (ctrl->getValue().asString() == "unmoderated") | ||
807 | { | ||
808 | data["params"]["moderated_mode"]["voice"] = false; | ||
809 | } | ||
810 | else if (ctrl->getValue().asString() == "moderated") | ||
811 | { | ||
812 | data["params"]["moderated_mode"]["voice"] = true; | ||
813 | } | ||
814 | |||
815 | struct ModerationModeResponder : public LLHTTPClient::Responder | ||
816 | { | ||
817 | virtual void error(U32 status, const std::string& reason) | ||
818 | { | ||
819 | llwarns << status << ": " << reason << llendl; | ||
820 | } | ||
821 | }; | ||
822 | |||
823 | LLHTTPClient::post(url, data, new ModerationModeResponder()); | ||
824 | } | ||
825 | |||
469 | // | 826 | // |
470 | // LLSpeakerMgr | 827 | // LLSpeakerMgr |
471 | // | 828 | // |
@@ -537,11 +894,16 @@ void LLSpeakerMgr::update() | |||
537 | if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id)) | 894 | if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id)) |
538 | { | 895 | { |
539 | speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id); | 896 | speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id); |
897 | BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id); | ||
898 | if (moderator_muted_voice != speakerp->mModeratorMutedVoice) | ||
899 | { | ||
900 | speakerp->mModeratorMutedVoice = moderator_muted_voice; | ||
901 | speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp)); | ||
902 | } | ||
540 | 903 | ||
541 | if (gVoiceClient->getOnMuteList(speaker_id)) | 904 | if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice) |
542 | { | 905 | { |
543 | speakerp->mStatus = LLSpeaker::STATUS_MUTED; | 906 | speakerp->mStatus = LLSpeaker::STATUS_MUTED; |
544 | speakerp->mDotColor = LLColor4::white; | ||
545 | } | 907 | } |
546 | else if (gVoiceClient->getIsSpeaking(speaker_id)) | 908 | else if (gVoiceClient->getIsSpeaking(speaker_id)) |
547 | { | 909 | { |
@@ -663,6 +1025,12 @@ void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_tex | |||
663 | } | 1025 | } |
664 | } | 1026 | } |
665 | 1027 | ||
1028 | const LLUUID LLSpeakerMgr::getSessionID() | ||
1029 | { | ||
1030 | return mVoiceChannel->getSessionID(); | ||
1031 | } | ||
1032 | |||
1033 | |||
666 | void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing) | 1034 | void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing) |
667 | { | 1035 | { |
668 | LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); | 1036 | LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id); |
@@ -704,57 +1072,134 @@ void LLIMSpeakerMgr::updateSpeakerList() | |||
704 | return; | 1072 | return; |
705 | } | 1073 | } |
706 | 1074 | ||
707 | void LLIMSpeakerMgr::processSpeakerList(LLSD list) | 1075 | void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers) |
708 | { | 1076 | { |
709 | for(LLSD::array_iterator list_it = list.beginArray(); | 1077 | if ( !speakers.isMap() ) return; |
710 | list_it != list.endArray(); | 1078 | |
711 | ++list_it) | 1079 | if ( speakers.has("agent_info") && speakers["agent_info"].isMap() ) |
712 | { | 1080 | { |
713 | LLUUID agent_id(list_it->asUUID()); | 1081 | LLSD::map_const_iterator speaker_it; |
1082 | for(speaker_it = speakers["agent_info"].beginMap(); | ||
1083 | speaker_it != speakers["agent_info"].endMap(); | ||
1084 | ++speaker_it) | ||
1085 | { | ||
1086 | LLUUID agent_id(speaker_it->first); | ||
714 | 1087 | ||
715 | setSpeaker(agent_id, "", LLSpeaker::STATUS_TEXT_ONLY); | 1088 | LLPointer<LLSpeaker> speakerp = setSpeaker( |
1089 | agent_id, | ||
1090 | "", | ||
1091 | LLSpeaker::STATUS_TEXT_ONLY); | ||
1092 | |||
1093 | if ( speaker_it->second.isMap() ) | ||
1094 | { | ||
1095 | speakerp->mIsModerator = speaker_it->second["is_moderator"]; | ||
1096 | speakerp->mModeratorMutedText = | ||
1097 | speaker_it->second["mutes"]["text"]; | ||
1098 | } | ||
1099 | } | ||
1100 | } | ||
1101 | else if ( speakers.has("agents" ) && speakers["agents"].isArray() ) | ||
1102 | { | ||
1103 | //older, more decprecated way. Need here for | ||
1104 | //using older version of servers | ||
1105 | LLSD::array_const_iterator speaker_it; | ||
1106 | for(speaker_it = speakers["agents"].beginArray(); | ||
1107 | speaker_it != speakers["agents"].endArray(); | ||
1108 | ++speaker_it) | ||
1109 | { | ||
1110 | const LLUUID agent_id = (*speaker_it).asUUID(); | ||
1111 | |||
1112 | LLPointer<LLSpeaker> speakerp = setSpeaker( | ||
1113 | agent_id, | ||
1114 | "", | ||
1115 | LLSpeaker::STATUS_TEXT_ONLY); | ||
1116 | } | ||
716 | } | 1117 | } |
717 | } | 1118 | } |
718 | 1119 | ||
719 | void LLIMSpeakerMgr::processSpeakerMap(LLSD map) | 1120 | void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) |
720 | { | 1121 | { |
721 | for(LLSD::map_iterator map_it = map.beginMap(); | 1122 | if ( !update.isMap() ) return; |
722 | map_it != map.endMap(); | 1123 | |
723 | ++map_it) | 1124 | if ( update.has("agent_updates") && update["agent_updates"].isMap() ) |
724 | { | 1125 | { |
725 | // add as new speaker | 1126 | LLSD::map_const_iterator update_it; |
726 | setSpeaker(LLUUID(map_it->first)); | 1127 | for( |
727 | } | 1128 | update_it = update["agent_updates"].beginMap(); |
728 | } | 1129 | update_it != update["agent_updates"].endMap(); |
1130 | ++update_it) | ||
1131 | { | ||
1132 | LLUUID agent_id(update_it->first); | ||
1133 | LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id); | ||
729 | 1134 | ||
1135 | LLSD agent_data = update_it->second; | ||
730 | 1136 | ||
1137 | if (agent_data.isMap() && agent_data.has("transition")) | ||
1138 | { | ||
1139 | if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull()) | ||
1140 | { | ||
1141 | speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; | ||
1142 | speakerp->mDotColor = INACTIVE_COLOR; | ||
1143 | speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); | ||
1144 | } | ||
1145 | else if (agent_data["transition"].asString() == "ENTER") | ||
1146 | { | ||
1147 | // add or update speaker | ||
1148 | speakerp = setSpeaker(agent_id); | ||
1149 | } | ||
1150 | else | ||
1151 | { | ||
1152 | llwarns << "bad membership list update " << ll_print_sd(agent_data["transition"]) << llendl; | ||
1153 | } | ||
1154 | } | ||
731 | 1155 | ||
732 | void LLIMSpeakerMgr::processSpeakerListUpdate(LLSD update) | 1156 | if (speakerp.isNull()) continue; |
733 | { | 1157 | |
734 | for(LLSD::map_iterator update_it = update.beginMap(); | 1158 | // should have a valid speaker from this point on |
735 | update_it != update.endMap(); | 1159 | if (agent_data.isMap() && agent_data.has("info")) |
736 | ++update_it) | 1160 | { |
1161 | LLSD agent_info = agent_data["info"]; | ||
1162 | |||
1163 | if (agent_info.has("is_moderator")) | ||
1164 | { | ||
1165 | speakerp->mIsModerator = agent_info["is_moderator"]; | ||
1166 | } | ||
1167 | |||
1168 | if (agent_info.has("mutes")) | ||
1169 | { | ||
1170 | speakerp->mModeratorMutedText = agent_info["mutes"]["text"]; | ||
1171 | } | ||
1172 | } | ||
1173 | } | ||
1174 | } | ||
1175 | else if ( update.has("updates") && update["updates"].isMap() ) | ||
737 | { | 1176 | { |
738 | LLUUID agent_id(update_it->first); | 1177 | LLSD::map_const_iterator update_it; |
739 | 1178 | for ( | |
740 | if (update_it->second.asString() == "LEAVE") | 1179 | update_it = update["updates"].beginMap(); |
1180 | update_it != update["updates"].endMap(); | ||
1181 | ++update_it) | ||
741 | { | 1182 | { |
1183 | LLUUID agent_id(update_it->first); | ||
742 | LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id); | 1184 | LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id); |
743 | if (speakerp) | 1185 | |
1186 | std::string agent_transition = update_it->second.asString(); | ||
1187 | if (agent_transition == "LEAVE" && speakerp.notNull()) | ||
744 | { | 1188 | { |
745 | speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; | 1189 | speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; |
746 | speakerp->mDotColor = INACTIVE_COLOR; | 1190 | speakerp->mDotColor = INACTIVE_COLOR; |
747 | speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); | 1191 | speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); |
748 | } | 1192 | } |
749 | } | 1193 | else if ( agent_transition == "ENTER") |
750 | else if (update_it->second.asString() == "ENTER") | 1194 | { |
751 | { | 1195 | // add or update speaker |
752 | // add or update speaker | 1196 | speakerp = setSpeaker(agent_id); |
753 | setSpeaker(agent_id); | 1197 | } |
754 | } | 1198 | else |
755 | else | 1199 | { |
756 | { | 1200 | llwarns << "bad membership list update " |
757 | llwarns << "LLIMSpeakerMgr::processSpeakerListUpdate() : bad membership list update " << ll_print_sd(update_it->second) << llendl; | 1201 | << agent_transition << llendl; |
1202 | } | ||
758 | } | 1203 | } |
759 | } | 1204 | } |
760 | } | 1205 | } |