aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloateractivespeakers.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:27 -0500
committerJacek Antonelli2008-08-15 23:45:27 -0500
commita8a62201ba762e98dff92cf49033e577fc34d8d4 (patch)
tree11f8513c5cdc222f2fac0c93eb724c089803c200 /linden/indra/newview/llfloateractivespeakers.cpp
parentSecond Life viewer sources 1.18.6.4-RC (diff)
downloadmeta-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.cpp563
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
49const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers 50const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
50const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f); 51const 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
117LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
118: LLEvent(source, "Speaker text moderation event")
119{
120}
121
122LLSD LLSpeakerTextModerationEvent::getValue()
123{
124 return LLString("text");
125}
126
127
128LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source)
129: LLEvent(source, "Speaker voice moderation event")
130{
131}
132
133LLSD LLSpeakerVoiceModerationEvent::getValue()
134{
135 return LLString("voice");
136}
137
110 138
111// helper sort class 139// helper sort class
112struct LLSortRecentSpeakers 140struct 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
135LLFloaterActiveSpeakers::LLFloaterActiveSpeakers(const LLSD& seed) : mPanel(NULL) 167LLFloaterActiveSpeakers::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//
215bool 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
196LLPanelActiveSpeakers::~LLPanelActiveSpeakers() 249LLPanelActiveSpeakers::~LLPanelActiveSpeakers()
@@ -201,6 +254,10 @@ LLPanelActiveSpeakers::~LLPanelActiveSpeakers()
201BOOL LLPanelActiveSpeakers::postBuild() 254BOOL 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
286void 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
221void LLPanelActiveSpeakers::refreshSpeakers() 304void 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
541void 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
387void LLPanelActiveSpeakers::onClickMuteTextCommit(LLUICtrl* ctrl, void* user_data) 557void 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
644void 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
658void LLPanelActiveSpeakers::onSelectSpeaker(LLUICtrl* source, void* user_data)
659{
660 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
661 panelp->handleSpeakerSelect();
662}
663
664//static
665void 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
730void 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
795void 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
1028const LLUUID LLSpeakerMgr::getSessionID()
1029{
1030 return mVoiceChannel->getSessionID();
1031}
1032
1033
666void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing) 1034void 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
707void LLIMSpeakerMgr::processSpeakerList(LLSD list) 1075void 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
719void LLIMSpeakerMgr::processSpeakerMap(LLSD map) 1120void 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
732void 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}