00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llfloateractivespeakers.h"
00035
00036 #include "llagent.h"
00037 #include "llvoavatar.h"
00038 #include "llfloateravatarinfo.h"
00039 #include "lluictrlfactory.h"
00040 #include "llviewercontrol.h"
00041 #include "llscrolllistctrl.h"
00042 #include "llbutton.h"
00043 #include "lltextbox.h"
00044 #include "llmutelist.h"
00045 #include "llviewerobjectlist.h"
00046 #include "llimpanel.h"
00047 #include "llsdutil.h"
00048 #include "llimview.h"
00049
00050 const F32 SPEAKER_TIMEOUT = 10.f;
00051 const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
00052 const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
00053 const F32 TYPING_ANIMATION_FPS = 2.5f;
00054
00055 LLSpeaker::LLSpeaker(const LLUUID& id, const LLString& name, const ESpeakerType type) :
00056 mStatus(LLSpeaker::STATUS_TEXT_ONLY),
00057 mLastSpokeTime(0.f),
00058 mSpeechVolume(0.f),
00059 mHasSpoken(FALSE),
00060 mDotColor(LLColor4::white),
00061 mID(id),
00062 mTyping(FALSE),
00063 mSortIndex(0),
00064 mType(type),
00065 mIsModerator(FALSE),
00066 mModeratorMutedVoice(FALSE),
00067 mModeratorMutedText(FALSE)
00068 {
00069 if (name.empty() && type == SPEAKER_AGENT)
00070 {
00071 lookupName();
00072 }
00073 else
00074 {
00075 mDisplayName = name;
00076 }
00077
00078 gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
00079
00080 mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
00081 }
00082
00083
00084 void LLSpeaker::lookupName()
00085 {
00086 gCacheName->getName(mID, onAvatarNameLookup, new LLHandle<LLSpeaker>(getHandle()));
00087 }
00088
00089
00090 void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const char* first, const char* last, BOOL is_group, void* user_data)
00091 {
00092 LLSpeaker* speaker_ptr = ((LLHandle<LLSpeaker>*)user_data)->get();
00093 delete (LLHandle<LLSpeaker>*)user_data;
00094
00095 if (speaker_ptr)
00096 {
00097 speaker_ptr->mDisplayName = llformat("%s %s", first, last);
00098 }
00099 }
00100
00101 LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
00102 : LLEvent(source, "Speaker text moderation event")
00103 {
00104 }
00105
00106 LLSD LLSpeakerTextModerationEvent::getValue()
00107 {
00108 return LLString("text");
00109 }
00110
00111
00112 LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source)
00113 : LLEvent(source, "Speaker voice moderation event")
00114 {
00115 }
00116
00117 LLSD LLSpeakerVoiceModerationEvent::getValue()
00118 {
00119 return LLString("voice");
00120 }
00121
00122 LLSpeakerListChangeEvent::LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id)
00123 : LLEvent(source, "Speaker added/removed from speaker mgr"),
00124 mSpeakerID(speaker_id)
00125 {
00126 }
00127
00128 LLSD LLSpeakerListChangeEvent::getValue()
00129 {
00130 return mSpeakerID;
00131 }
00132
00133
00134 struct LLSortRecentSpeakers
00135 {
00136 bool operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const;
00137 };
00138
00139 bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const
00140 {
00141
00142 if (lhs->mStatus != rhs->mStatus)
00143 {
00144 return (lhs->mStatus < rhs->mStatus);
00145 }
00146
00147
00148 if(lhs->mLastSpokeTime != rhs->mLastSpokeTime)
00149 {
00150 return (lhs->mLastSpokeTime > rhs->mLastSpokeTime);
00151 }
00152
00153
00154 return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
00155 }
00156
00157
00158
00159
00160
00161 LLFloaterActiveSpeakers::LLFloaterActiveSpeakers(const LLSD& seed) : mPanel(NULL)
00162 {
00163 mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL);
00164
00165 BOOL no_open = FALSE;
00166 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_active_speakers.xml", &getFactoryMap(), no_open);
00167
00168
00169 mPanel->refreshSpeakers();
00170 }
00171
00172 LLFloaterActiveSpeakers::~LLFloaterActiveSpeakers()
00173 {
00174 }
00175
00176 void LLFloaterActiveSpeakers::onOpen()
00177 {
00178 gSavedSettings.setBOOL("ShowActiveSpeakers", TRUE);
00179 }
00180
00181 void LLFloaterActiveSpeakers::onClose(bool app_quitting)
00182 {
00183 if (!app_quitting)
00184 {
00185 gSavedSettings.setBOOL("ShowActiveSpeakers", FALSE);
00186 }
00187 setVisible(FALSE);
00188 }
00189
00190 void LLFloaterActiveSpeakers::draw()
00191 {
00192
00193 mPanel->refreshSpeakers();
00194 LLFloater::draw();
00195 }
00196
00197 BOOL LLFloaterActiveSpeakers::postBuild()
00198 {
00199 mPanel = getChild<LLPanelActiveSpeakers>("active_speakers_panel");
00200 return TRUE;
00201 }
00202
00203 void LLFloaterActiveSpeakers::onChange()
00204 {
00205
00206 }
00207
00208
00209 void* LLFloaterActiveSpeakers::createSpeakersPanel(void* data)
00210 {
00211
00212 return new LLPanelActiveSpeakers(LLActiveSpeakerMgr::getInstance(), FALSE);
00213 }
00214
00215
00216
00217
00218 bool LLPanelActiveSpeakers::SpeakerMuteListener::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00219 {
00220 LLPointer<LLSpeaker> speakerp = (LLSpeaker*)event->getSource();
00221 if (speakerp.isNull()) return false;
00222
00223
00224 if (event->getValue().asString() == "voice")
00225 {
00226 mPanel->childSetValue("moderator_allow_voice", !speakerp->mModeratorMutedVoice);
00227 }
00228 if (event->getValue().asString() == "text")
00229 {
00230 mPanel->childSetValue("moderator_allow_text", !speakerp->mModeratorMutedText);
00231 }
00232 return true;
00233 }
00234
00235
00236
00237
00238
00239 bool LLPanelActiveSpeakers::SpeakerAddListener::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00240 {
00241 mPanel->addSpeaker(event->getValue().asUUID());
00242 return true;
00243 }
00244
00245
00246
00247
00248
00249 bool LLPanelActiveSpeakers::SpeakerRemoveListener::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00250 {
00251 mPanel->removeSpeaker(event->getValue().asUUID());
00252 return true;
00253 }
00254
00255
00256
00257
00258 bool LLPanelActiveSpeakers::SpeakerClearListener::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
00259 {
00260 mPanel->mSpeakerList->clearRows();
00261 return true;
00262 }
00263
00264
00265
00266
00267
00268 LLPanelActiveSpeakers::LLPanelActiveSpeakers(LLSpeakerMgr* data_source, BOOL show_text_chatters) :
00269 mSpeakerList(NULL),
00270 mMuteVoiceCtrl(NULL),
00271 mMuteTextCtrl(NULL),
00272 mNameText(NULL),
00273 mProfileBtn(NULL),
00274 mShowTextChatters(show_text_chatters),
00275 mSpeakerMgr(data_source)
00276 {
00277 setMouseOpaque(FALSE);
00278 mSpeakerMuteListener = new SpeakerMuteListener(this);
00279 mSpeakerAddListener = new SpeakerAddListener(this);
00280 mSpeakerRemoveListener = new SpeakerRemoveListener(this);
00281 mSpeakerClearListener = new SpeakerClearListener(this);
00282
00283 mSpeakerMgr->addListener(mSpeakerAddListener, "add");
00284 mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
00285 mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
00286 }
00287
00288 BOOL LLPanelActiveSpeakers::postBuild()
00289 {
00290 std::string sort_column = gSavedSettings.getString(LLString("FloaterActiveSpeakersSortColumn"));
00291 BOOL sort_ascending = gSavedSettings.getBOOL( LLString("FloaterActiveSpeakersSortAscending"));
00292
00293 mSpeakerList = getChild<LLScrollListCtrl>("speakers_list");
00294 mSpeakerList->sortByColumn(sort_column, sort_ascending);
00295 mSpeakerList->setDoubleClickCallback(onDoubleClickSpeaker);
00296 mSpeakerList->setCommitOnSelectionChange(TRUE);
00297 mSpeakerList->setCommitCallback(onSelectSpeaker);
00298 mSpeakerList->setSortChangedCallback(onSortChanged);
00299 mSpeakerList->setCallbackUserData(this);
00300
00301 mMuteTextCtrl = getChild<LLUICtrl>("mute_text_btn");
00302 childSetCommitCallback("mute_text_btn", onClickMuteTextCommit, this);
00303
00304 mMuteVoiceCtrl = getChild<LLUICtrl>("mute_btn");
00305 childSetCommitCallback("mute_btn", onClickMuteVoiceCommit, this);
00306 childSetAction("mute_btn", onClickMuteVoice, this);
00307
00308 childSetCommitCallback("speaker_volume", onVolumeChange, this);
00309
00310 mNameText = getChild<LLTextBox>("resident_name");
00311
00312 mProfileBtn = getChild<LLButton>("profile_btn");
00313 childSetAction("profile_btn", onClickProfile, this);
00314
00315 childSetCommitCallback("moderator_allow_voice", onModeratorMuteVoice, this);
00316 childSetCommitCallback("moderator_allow_text", onModeratorMuteText, this);
00317 childSetCommitCallback("moderation_mode", onChangeModerationMode, this);
00318
00319
00320 handleSpeakerSelect();
00321
00322 return TRUE;
00323 }
00324
00325 void LLPanelActiveSpeakers::addSpeaker(const LLUUID& speaker_id)
00326 {
00327 if (mSpeakerList->getItemIndex(speaker_id) >= 0)
00328 {
00329
00330 return;
00331 }
00332
00333 LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id);
00334 if (speakerp)
00335 {
00336
00337 LLString speaking_order_sort_string = llformat("%010d", speakerp->mSortIndex);
00338
00339 LLSD row;
00340 row["id"] = speaker_id;
00341
00342 LLSD& columns = row["columns"];
00343
00344 columns[0]["column"] = "icon_speaking_status";
00345 columns[0]["type"] = "icon";
00346 columns[0]["value"] = "icn_active-speakers-dot-lvl0.tga";
00347
00348 LLString speaker_name;
00349 if (speakerp->mDisplayName.empty())
00350 {
00351 speaker_name = LLCacheName::getDefaultName();
00352 }
00353 else
00354 {
00355 speaker_name = speakerp->mDisplayName;
00356 }
00357 columns[1]["column"] = "speaker_name";
00358 columns[1]["type"] = "text";
00359 columns[1]["value"] = speaker_name;
00360
00361 columns[2]["column"] = "speaking_status";
00362 columns[2]["type"] = "text";
00363
00364
00365 columns[2]["value"] = speaking_order_sort_string;
00366
00367 mSpeakerList->addElement(row);
00368 }
00369 }
00370
00371 void LLPanelActiveSpeakers::removeSpeaker(const LLUUID& speaker_id)
00372 {
00373 mSpeakerList->deleteSingleItem(mSpeakerList->getItemIndex(speaker_id));
00374 }
00375
00376 void LLPanelActiveSpeakers::handleSpeakerSelect()
00377 {
00378 LLUUID speaker_id = mSpeakerList->getValue().asUUID();
00379 LLPointer<LLSpeaker> selected_speakerp = mSpeakerMgr->findSpeaker(speaker_id);
00380
00381 if (selected_speakerp.notNull())
00382 {
00383
00384
00385
00386 childSetValue("moderator_allow_voice", selected_speakerp ? !selected_speakerp->mModeratorMutedVoice : TRUE);
00387 childSetValue("moderator_allow_text", selected_speakerp ? !selected_speakerp->mModeratorMutedText : TRUE);
00388
00389 mSpeakerMuteListener->clearDispatchers();
00390 selected_speakerp->addListener(mSpeakerMuteListener);
00391 }
00392 }
00393
00394 void LLPanelActiveSpeakers::refreshSpeakers()
00395 {
00396
00397 LLUUID selected_id = mSpeakerList->getSelectedValue().asUUID();
00398 S32 scroll_pos = mSpeakerList->getScrollInterface()->getScrollPos();
00399
00400 mSpeakerMgr->update();
00401
00402 const LLString icon_image_0 = "icn_active-speakers-dot-lvl0.tga";
00403 const LLString icon_image_1 = "icn_active-speakers-dot-lvl1.tga";
00404 const LLString icon_image_2 = "icn_active-speakers-dot-lvl2.tga";
00405
00406 std::vector<LLScrollListItem*> items = mSpeakerList->getAllData();
00407
00408 LLString mute_icon_image = "mute_icon.tga";
00409
00410 LLSpeakerMgr::speaker_list_t speaker_list;
00411 mSpeakerMgr->getSpeakerList(&speaker_list, mShowTextChatters);
00412 for (std::vector<LLScrollListItem*>::iterator item_it = items.begin();
00413 item_it != items.end();
00414 ++item_it)
00415 {
00416 LLScrollListItem* itemp = (*item_it);
00417 LLUUID speaker_id = itemp->getUUID();
00418
00419 LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(speaker_id);
00420 if (!speakerp)
00421 {
00422 continue;
00423 }
00424
00425
00426 LLString speaking_order_sort_string = llformat("%010d", speakerp->mSortIndex);
00427
00428 LLScrollListCell* icon_cell = itemp->getColumn(0);
00429 if (icon_cell)
00430 {
00431
00432 LLString icon_image_id;
00433
00434 S32 icon_image_idx = llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f));
00435 switch(icon_image_idx)
00436 {
00437 case 0:
00438 icon_image_id = icon_image_0;
00439 break;
00440 case 1:
00441 icon_image_id = icon_image_1;
00442 break;
00443 case 2:
00444 icon_image_id = icon_image_2;
00445 break;
00446 }
00447
00448 LLColor4 icon_color;
00449 if (speakerp->mStatus == LLSpeaker::STATUS_MUTED)
00450 {
00451 icon_cell->setValue(mute_icon_image);
00452 if(speakerp->mModeratorMutedVoice)
00453 {
00454 icon_color.setVec(0.5f, 0.5f, 0.5f, 1.f);
00455 }
00456 else
00457 {
00458 icon_color.setVec(1.f, 71.f / 255.f, 71.f / 255.f, 1.f);
00459 }
00460 }
00461 else
00462 {
00463 icon_cell->setValue(icon_image_id);
00464 icon_color = speakerp->mDotColor;
00465
00466 if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE)
00467 {
00468
00469 icon_color.setVec(0.f, 0.f, 0.f, 0.f);
00470 }
00471 }
00472
00473 icon_cell->setColor(icon_color);
00474
00475 if (speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE && speakerp->mStatus != LLSpeaker::STATUS_MUTED)
00476 {
00477
00478 icon_cell->setColor(LLColor4::transparent);
00479 }
00480 }
00481
00482
00483 LLScrollListCell* name_cell = itemp->getColumn(1);
00484 if (name_cell)
00485 {
00486
00487 if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL)
00488 {
00489
00490 name_cell->setColor(LLColor4::grey4);
00491 }
00492 else
00493 {
00494 name_cell->setColor(LLColor4::black);
00495 }
00496
00497 LLString speaker_name;
00498 if (speakerp->mDisplayName.empty())
00499 {
00500 speaker_name = LLCacheName::getDefaultName();
00501 }
00502 else
00503 {
00504 speaker_name = speakerp->mDisplayName;
00505 }
00506
00507 if (speakerp->mIsModerator)
00508 {
00509 speaker_name += LLString(" ") + getString("moderator_label");
00510 }
00511
00512 name_cell->setValue(speaker_name);
00513 ((LLScrollListText*)name_cell)->setFontStyle(speakerp->mIsModerator ? LLFontGL::BOLD : LLFontGL::NORMAL);
00514 }
00515
00516
00517 LLScrollListCell* speaking_status_cell = itemp->getColumn(2);
00518 if (speaking_status_cell)
00519 {
00520
00521 speaking_status_cell->setValue(speaking_order_sort_string);
00522 }
00523 }
00524
00525
00526 mSpeakerList->setSorted(FALSE);
00527
00528 LLPointer<LLSpeaker> selected_speakerp = mSpeakerMgr->findSpeaker(selected_id);
00529
00530 if (mMuteVoiceCtrl)
00531 {
00532 mMuteVoiceCtrl->setValue(LLMuteList::getInstance()->isMuted(selected_id, LLMute::flagVoiceChat));
00533 mMuteVoiceCtrl->setEnabled(LLVoiceClient::voiceEnabled()
00534 && gVoiceClient->getVoiceEnabled(selected_id)
00535 && selected_id.notNull()
00536 && selected_id != gAgent.getID()
00537 && (selected_speakerp.notNull() && selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT));
00538 }
00539 if (mMuteTextCtrl)
00540 {
00541 mMuteTextCtrl->setValue(LLMuteList::getInstance()->isMuted(selected_id, LLMute::flagTextChat));
00542 mMuteTextCtrl->setEnabled(selected_id.notNull()
00543 && selected_id != gAgent.getID()
00544 && selected_speakerp.notNull()
00545 && !LLMuteList::getInstance()->isLinden(selected_speakerp->mDisplayName));
00546 }
00547 childSetValue("speaker_volume", gVoiceClient->getUserVolume(selected_id));
00548 childSetEnabled("speaker_volume", LLVoiceClient::voiceEnabled()
00549 && gVoiceClient->getVoiceEnabled(selected_id)
00550 && selected_id.notNull()
00551 && selected_id != gAgent.getID()
00552 && (selected_speakerp.notNull() && selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT));
00553
00554 childSetEnabled(
00555 "moderator_controls_label",
00556 selected_id.notNull());
00557
00558 childSetEnabled(
00559 "moderator_allow_voice",
00560 selected_id.notNull()
00561 && mSpeakerMgr->isVoiceActive()
00562 && gVoiceClient->getVoiceEnabled(selected_id));
00563
00564 childSetEnabled(
00565 "moderator_allow_text",
00566 selected_id.notNull());
00567
00568 if (mProfileBtn)
00569 {
00570 mProfileBtn->setEnabled(selected_id.notNull());
00571 }
00572
00573
00574 if (mNameText)
00575 {
00576 if (selected_speakerp)
00577 {
00578 mNameText->setValue(selected_speakerp->mDisplayName);
00579 }
00580 else
00581 {
00582 mNameText->setValue(LLString::null);
00583 }
00584 }
00585
00586
00587 LLPointer<LLSpeaker> self_speakerp = mSpeakerMgr->findSpeaker(gAgent.getID());
00588 if(self_speakerp)
00589 {
00590 childSetVisible("moderation_mode_panel", self_speakerp->mIsModerator && mSpeakerMgr->isVoiceActive());
00591 childSetVisible("moderator_controls", self_speakerp->mIsModerator);
00592 }
00593
00594
00595 mSpeakerList->getScrollInterface()->setScrollPos(scroll_pos);
00596 }
00597
00598 void LLPanelActiveSpeakers::setSpeaker(const LLUUID& id, const LLString& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
00599 {
00600 mSpeakerMgr->setSpeaker(id, name, status, type);
00601 }
00602
00603 void LLPanelActiveSpeakers::setVoiceModerationCtrlMode(
00604 const BOOL& moderated_voice)
00605 {
00606 LLUICtrl* voice_moderation_ctrl = getChild<LLUICtrl>("moderation_mode");
00607
00608 if ( voice_moderation_ctrl )
00609 {
00610 std::string value;
00611
00612 value = moderated_voice ? "moderated" : "unmoderated";
00613 voice_moderation_ctrl->setValue(value);
00614 }
00615 }
00616
00617
00618 void LLPanelActiveSpeakers::onClickMuteTextCommit(LLUICtrl* ctrl, void* user_data)
00619 {
00620 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00621 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
00622 BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagTextChat);
00623 std::string name;
00624
00625
00626 LLPointer<LLSpeaker> speakerp = panelp->mSpeakerMgr->findSpeaker(speaker_id);
00627 if (speakerp.isNull())
00628 {
00629 return;
00630 }
00631
00632 name = speakerp->mDisplayName;
00633
00634 LLMute mute(speaker_id, name, speakerp->mType == LLSpeaker::SPEAKER_AGENT ? LLMute::AGENT : LLMute::OBJECT);
00635
00636 if (!is_muted)
00637 {
00638 LLMuteList::getInstance()->add(mute, LLMute::flagTextChat);
00639 }
00640 else
00641 {
00642 LLMuteList::getInstance()->remove(mute, LLMute::flagTextChat);
00643 }
00644 }
00645
00646
00647 void LLPanelActiveSpeakers::onClickMuteVoice(void* user_data)
00648 {
00649 onClickMuteVoiceCommit(NULL, user_data);
00650 }
00651
00652
00653 void LLPanelActiveSpeakers::onClickMuteVoiceCommit(LLUICtrl* ctrl, void* user_data)
00654 {
00655 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00656 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
00657 BOOL is_muted = LLMuteList::getInstance()->isMuted(speaker_id, LLMute::flagVoiceChat);
00658 std::string name;
00659
00660 LLPointer<LLSpeaker> speakerp = panelp->mSpeakerMgr->findSpeaker(speaker_id);
00661 if (speakerp.isNull())
00662 {
00663 return;
00664 }
00665
00666 name = speakerp->mDisplayName;
00667
00668
00669 LLMute mute(speaker_id, name, LLMute::AGENT);
00670
00671 if (!is_muted)
00672 {
00673 LLMuteList::getInstance()->add(mute, LLMute::flagVoiceChat);
00674 }
00675 else
00676 {
00677 LLMuteList::getInstance()->remove(mute, LLMute::flagVoiceChat);
00678 }
00679 }
00680
00681
00682
00683 void LLPanelActiveSpeakers::onVolumeChange(LLUICtrl* source, void* user_data)
00684 {
00685 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00686 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
00687
00688 F32 new_volume = (F32)panelp->childGetValue("speaker_volume").asReal();
00689 gVoiceClient->setUserVolume(speaker_id, new_volume);
00690
00691
00692 LLMuteList::getInstance()->setSavedResidentVolume(speaker_id, new_volume);
00693 }
00694
00695
00696 void LLPanelActiveSpeakers::onClickProfile(void* user_data)
00697 {
00698 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00699 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
00700
00701 LLFloaterAvatarInfo::showFromDirectory(speaker_id);
00702 }
00703
00704
00705 void LLPanelActiveSpeakers::onDoubleClickSpeaker(void* user_data)
00706 {
00707 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00708 LLUUID speaker_id = panelp->mSpeakerList->getValue().asUUID();
00709
00710 LLPointer<LLSpeaker> speakerp = panelp->mSpeakerMgr->findSpeaker(speaker_id);
00711
00712 if (speaker_id != gAgent.getID() && speakerp.notNull())
00713 {
00714 gIMMgr->addSession(speakerp->mDisplayName, IM_NOTHING_SPECIAL, speaker_id);
00715 }
00716 }
00717
00718
00719 void LLPanelActiveSpeakers::onSelectSpeaker(LLUICtrl* source, void* user_data)
00720 {
00721 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00722 panelp->handleSpeakerSelect();
00723 }
00724
00725
00726
00727 void LLPanelActiveSpeakers::onSortChanged(void* user_data)
00728 {
00729 LLPanelActiveSpeakers* panelp = (LLPanelActiveSpeakers*)user_data;
00730 std::string sort_column = panelp->mSpeakerList->getSortColumnName();
00731 BOOL sort_ascending = panelp->mSpeakerList->getSortAscending();
00732 gSavedSettings.setString(LLString("FloaterActiveSpeakersSortColumn"), sort_column);
00733 gSavedSettings.setBOOL( LLString("FloaterActiveSpeakersSortAscending"), sort_ascending);
00734 }
00735
00736
00737
00738 void LLPanelActiveSpeakers::onModeratorMuteVoice(LLUICtrl* ctrl, void* user_data)
00739 {
00740 LLPanelActiveSpeakers* self = (LLPanelActiveSpeakers*)user_data;
00741 LLUICtrl* speakers_list = self->getChild<LLUICtrl>("speakers_list");
00742 if (!speakers_list || !gAgent.getRegion()) return;
00743
00744 std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
00745 LLSD data;
00746 data["method"] = "mute update";
00747 data["session-id"] = self->mSpeakerMgr->getSessionID();
00748 data["params"] = LLSD::emptyMap();
00749 data["params"]["agent_id"] = speakers_list->getValue();
00750 data["params"]["mutes"] = LLSD::emptyMap();
00751
00752 data["params"]["mutes"]["voice"] = !ctrl->getValue();
00753
00754 class MuteVoiceResponder : public LLHTTPClient::Responder
00755 {
00756 public:
00757 MuteVoiceResponder(const LLUUID& session_id)
00758 {
00759 mSessionID = session_id;
00760 }
00761
00762 virtual void error(U32 status, const std::string& reason)
00763 {
00764 llwarns << status << ": " << reason << llendl;
00765
00766 if ( gIMMgr )
00767 {
00768
00769
00770 LLFloaterIMPanel* floaterp;
00771
00772 floaterp = gIMMgr->findFloaterBySession(mSessionID);
00773
00774 if ( floaterp )
00775 {
00776 if ( 403 == status )
00777 {
00778 floaterp->showSessionEventError(
00779 "mute",
00780 "not_a_moderator");
00781 }
00782 else
00783 {
00784 floaterp->showSessionEventError(
00785 "mute",
00786 "generic");
00787 }
00788 }
00789 }
00790 }
00791
00792 private:
00793 LLUUID mSessionID;
00794 };
00795
00796 LLHTTPClient::post(
00797 url,
00798 data,
00799 new MuteVoiceResponder(self->mSpeakerMgr->getSessionID()));
00800 }
00801
00802
00803 void LLPanelActiveSpeakers::onModeratorMuteText(LLUICtrl* ctrl, void* user_data)
00804 {
00805 LLPanelActiveSpeakers* self = (LLPanelActiveSpeakers*)user_data;
00806 LLUICtrl* speakers_list = self->getChild<LLUICtrl>("speakers_list");
00807 if (!speakers_list || !gAgent.getRegion()) return;
00808
00809 std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
00810 LLSD data;
00811 data["method"] = "mute update";
00812 data["session-id"] = self->mSpeakerMgr->getSessionID();
00813 data["params"] = LLSD::emptyMap();
00814 data["params"]["agent_id"] = speakers_list->getValue();
00815 data["params"]["mutes"] = LLSD::emptyMap();
00816
00817 data["params"]["mutes"]["text"] = !ctrl->getValue();
00818
00819 class MuteTextResponder : public LLHTTPClient::Responder
00820 {
00821 public:
00822 MuteTextResponder(const LLUUID& session_id)
00823 {
00824 mSessionID = session_id;
00825 }
00826
00827 virtual void error(U32 status, const std::string& reason)
00828 {
00829 llwarns << status << ": " << reason << llendl;
00830
00831 if ( gIMMgr )
00832 {
00833
00834
00835 LLFloaterIMPanel* floaterp;
00836
00837 floaterp = gIMMgr->findFloaterBySession(mSessionID);
00838
00839 if ( floaterp )
00840 {
00841 if ( 403 == status )
00842 {
00843 floaterp->showSessionEventError(
00844 "mute",
00845 "not_a_moderator");
00846 }
00847 else
00848 {
00849 floaterp->showSessionEventError(
00850 "mute",
00851 "generic");
00852 }
00853 }
00854 }
00855 }
00856
00857 private:
00858 LLUUID mSessionID;
00859 };
00860
00861 LLHTTPClient::post(
00862 url,
00863 data,
00864 new MuteTextResponder(self->mSpeakerMgr->getSessionID()));
00865 }
00866
00867
00868 void LLPanelActiveSpeakers::onChangeModerationMode(LLUICtrl* ctrl, void* user_data)
00869 {
00870 LLPanelActiveSpeakers* self = (LLPanelActiveSpeakers*)user_data;
00871 if (!gAgent.getRegion()) return;
00872
00873 std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest");
00874 LLSD data;
00875 data["method"] = "session update";
00876 data["session-id"] = self->mSpeakerMgr->getSessionID();
00877 data["params"] = LLSD::emptyMap();
00878 data["params"]["moderated_mode"] = LLSD::emptyMap();
00879 if (ctrl->getValue().asString() == "unmoderated")
00880 {
00881 data["params"]["moderated_mode"]["voice"] = false;
00882 }
00883 else if (ctrl->getValue().asString() == "moderated")
00884 {
00885 data["params"]["moderated_mode"]["voice"] = true;
00886 }
00887
00888 struct ModerationModeResponder : public LLHTTPClient::Responder
00889 {
00890 virtual void error(U32 status, const std::string& reason)
00891 {
00892 llwarns << status << ": " << reason << llendl;
00893 }
00894 };
00895
00896 LLHTTPClient::post(url, data, new ModerationModeResponder());
00897 }
00898
00899
00900
00901
00902
00903 LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
00904 mVoiceChannel(channelp)
00905 {
00906 }
00907
00908 LLSpeakerMgr::~LLSpeakerMgr()
00909 {
00910 }
00911
00912 LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const LLString& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
00913 {
00914 if (id.isNull()) return NULL;
00915
00916 LLPointer<LLSpeaker> speakerp;
00917 if (mSpeakers.find(id) == mSpeakers.end())
00918 {
00919 speakerp = new LLSpeaker(id, name, type);
00920 speakerp->mStatus = status;
00921 mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
00922 mSpeakersSorted.push_back(speakerp);
00923 fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
00924 }
00925 else
00926 {
00927 speakerp = findSpeaker(id);
00928 if (speakerp.notNull())
00929 {
00930
00931 speakerp->mStatus = llmin(speakerp->mStatus, status);
00932 speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
00933
00934
00935
00936 if (type == LLSpeaker::SPEAKER_AGENT)
00937 {
00938 speakerp->mType = LLSpeaker::SPEAKER_AGENT;
00939 speakerp->lookupName();
00940 }
00941 }
00942 }
00943
00944 return speakerp;
00945 }
00946
00947 void LLSpeakerMgr::update()
00948 {
00949 if (!gVoiceClient)
00950 {
00951 return;
00952 }
00953
00954 LLColor4 speaking_color = gSavedSettings.getColor4("SpeakingColor");
00955 LLColor4 overdriven_color = gSavedSettings.getColor4("OverdrivenColor");
00956
00957 updateSpeakerList();
00958
00959
00960 BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
00961 for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
00962 {
00963 LLUUID speaker_id = speaker_it->first;
00964 LLSpeaker* speakerp = speaker_it->second;
00965
00966 speaker_map_t::iterator cur_speaker_it = speaker_it++;
00967
00968 if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
00969 {
00970 speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id);
00971 BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id);
00972 if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
00973 {
00974 speakerp->mModeratorMutedVoice = moderator_muted_voice;
00975 speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
00976 }
00977
00978 if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
00979 {
00980 speakerp->mStatus = LLSpeaker::STATUS_MUTED;
00981 }
00982 else if (gVoiceClient->getIsSpeaking(speaker_id))
00983 {
00984
00985 if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
00986 {
00987 speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
00988 speakerp->mHasSpoken = TRUE;
00989 }
00990 speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
00991
00992 speakerp->mDotColor = speaking_color;
00993 if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
00994 {
00995 speakerp->mDotColor = overdriven_color;
00996 }
00997 }
00998 else
00999 {
01000 speakerp->mSpeechVolume = 0.f;
01001 speakerp->mDotColor = ACTIVE_COLOR;
01002
01003 if (speakerp->mHasSpoken)
01004 {
01005
01006 speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN;
01007 }
01008 else
01009 {
01010
01011 speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE;
01012 }
01013 }
01014 }
01015
01016 else if (speakerp->mStatus != LLSpeaker::STATUS_NOT_IN_CHANNEL)
01017 {
01018 speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY;
01019 speakerp->mSpeechVolume = 0.f;
01020 speakerp->mDotColor = ACTIVE_COLOR;
01021 }
01022 }
01023
01024
01025 std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
01026
01027
01028
01029
01030 S32 recent_speaker_count = 0;
01031 S32 sort_index = 0;
01032 speaker_list_t::iterator sorted_speaker_it;
01033 for(sorted_speaker_it = mSpeakersSorted.begin();
01034 sorted_speaker_it != mSpeakersSorted.end(); )
01035 {
01036 LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
01037
01038
01039 if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
01040 {
01041 speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
01042 recent_speaker_count++;
01043 }
01044
01045
01046 speakerp->mSortIndex = sort_index++;
01047
01048
01049 if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
01050 {
01051 fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
01052
01053 mSpeakers.erase(speakerp->mID);
01054 sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
01055 }
01056 else
01057 {
01058 ++sorted_speaker_it;
01059 }
01060 }
01061 }
01062
01063 void LLSpeakerMgr::updateSpeakerList()
01064 {
01065
01066 if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
01067 {
01068 LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList();
01069 LLVoiceClient::participantMap::iterator participant_it;
01070
01071
01072 for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it)
01073 {
01074 LLVoiceClient::participantState* participantp = participant_it->second;
01075 setSpeaker(participantp->mAvatarID, "", LLSpeaker::STATUS_VOICE_ACTIVE);
01076 }
01077 }
01078 }
01079
01080 const LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
01081 {
01082 speaker_map_t::iterator found_it = mSpeakers.find(speaker_id);
01083 if (found_it == mSpeakers.end())
01084 {
01085 return NULL;
01086 }
01087 return found_it->second;
01088 }
01089
01090 void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text)
01091 {
01092 speaker_list->clear();
01093 for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
01094 {
01095 LLPointer<LLSpeaker> speakerp = speaker_it->second;
01096
01097 if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY)
01098 {
01099 speaker_list->push_back(speakerp);
01100 }
01101 }
01102 }
01103
01104 const LLUUID LLSpeakerMgr::getSessionID()
01105 {
01106 return mVoiceChannel->getSessionID();
01107 }
01108
01109
01110 void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing)
01111 {
01112 LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
01113 if (speakerp.notNull())
01114 {
01115 speakerp->mTyping = typing;
01116 }
01117 }
01118
01119
01120 void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
01121 {
01122 LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
01123 if (speakerp.notNull())
01124 {
01125 speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
01126 speakerp->mHasSpoken = TRUE;
01127 }
01128 }
01129
01130 BOOL LLSpeakerMgr::isVoiceActive()
01131 {
01132
01133 return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
01134 }
01135
01136
01137
01138
01139
01140 LLIMSpeakerMgr::LLIMSpeakerMgr(LLVoiceChannel* channel) : LLSpeakerMgr(channel)
01141 {
01142 }
01143
01144 void LLIMSpeakerMgr::updateSpeakerList()
01145 {
01146
01147
01148 return;
01149 }
01150
01151 void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
01152 {
01153 if ( !speakers.isMap() ) return;
01154
01155 if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
01156 {
01157 LLSD::map_const_iterator speaker_it;
01158 for(speaker_it = speakers["agent_info"].beginMap();
01159 speaker_it != speakers["agent_info"].endMap();
01160 ++speaker_it)
01161 {
01162 LLUUID agent_id(speaker_it->first);
01163
01164 LLPointer<LLSpeaker> speakerp = setSpeaker(
01165 agent_id,
01166 "",
01167 LLSpeaker::STATUS_TEXT_ONLY);
01168
01169 if ( speaker_it->second.isMap() )
01170 {
01171 speakerp->mIsModerator = speaker_it->second["is_moderator"];
01172 speakerp->mModeratorMutedText =
01173 speaker_it->second["mutes"]["text"];
01174 }
01175 }
01176 }
01177 else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
01178 {
01179
01180
01181 LLSD::array_const_iterator speaker_it;
01182 for(speaker_it = speakers["agents"].beginArray();
01183 speaker_it != speakers["agents"].endArray();
01184 ++speaker_it)
01185 {
01186 const LLUUID agent_id = (*speaker_it).asUUID();
01187
01188 LLPointer<LLSpeaker> speakerp = setSpeaker(
01189 agent_id,
01190 "",
01191 LLSpeaker::STATUS_TEXT_ONLY);
01192 }
01193 }
01194 }
01195
01196 void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
01197 {
01198 if ( !update.isMap() ) return;
01199
01200 if ( update.has("agent_updates") && update["agent_updates"].isMap() )
01201 {
01202 LLSD::map_const_iterator update_it;
01203 for(
01204 update_it = update["agent_updates"].beginMap();
01205 update_it != update["agent_updates"].endMap();
01206 ++update_it)
01207 {
01208 LLUUID agent_id(update_it->first);
01209 LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
01210
01211 LLSD agent_data = update_it->second;
01212
01213 if (agent_data.isMap() && agent_data.has("transition"))
01214 {
01215 if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
01216 {
01217 speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
01218 speakerp->mDotColor = INACTIVE_COLOR;
01219 speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
01220 }
01221 else if (agent_data["transition"].asString() == "ENTER")
01222 {
01223
01224 speakerp = setSpeaker(agent_id);
01225 }
01226 else
01227 {
01228 llwarns << "bad membership list update " << ll_print_sd(agent_data["transition"]) << llendl;
01229 }
01230 }
01231
01232 if (speakerp.isNull()) continue;
01233
01234
01235 if (agent_data.isMap() && agent_data.has("info"))
01236 {
01237 LLSD agent_info = agent_data["info"];
01238
01239 if (agent_info.has("is_moderator"))
01240 {
01241 speakerp->mIsModerator = agent_info["is_moderator"];
01242 }
01243
01244 if (agent_info.has("mutes"))
01245 {
01246 speakerp->mModeratorMutedText = agent_info["mutes"]["text"];
01247 }
01248 }
01249 }
01250 }
01251 else if ( update.has("updates") && update["updates"].isMap() )
01252 {
01253 LLSD::map_const_iterator update_it;
01254 for (
01255 update_it = update["updates"].beginMap();
01256 update_it != update["updates"].endMap();
01257 ++update_it)
01258 {
01259 LLUUID agent_id(update_it->first);
01260 LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
01261
01262 std::string agent_transition = update_it->second.asString();
01263 if (agent_transition == "LEAVE" && speakerp.notNull())
01264 {
01265 speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
01266 speakerp->mDotColor = INACTIVE_COLOR;
01267 speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
01268 }
01269 else if ( agent_transition == "ENTER")
01270 {
01271
01272 speakerp = setSpeaker(agent_id);
01273 }
01274 else
01275 {
01276 llwarns << "bad membership list update "
01277 << agent_transition << llendl;
01278 }
01279 }
01280 }
01281 }
01282
01283
01284
01285
01286
01287
01288 LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL)
01289 {
01290 }
01291
01292 void LLActiveSpeakerMgr::updateSpeakerList()
01293 {
01294
01295 mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
01296
01297
01298 if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
01299 {
01300 fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
01301 mSpeakers.clear();
01302 mSpeakersSorted.clear();
01303 mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
01304 }
01305 LLSpeakerMgr::updateSpeakerList();
01306
01307
01308 for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
01309 {
01310 LLUUID speaker_id = speaker_it->first;
01311 LLSpeaker* speakerp = speaker_it->second;
01312 if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
01313 {
01314
01315 speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
01316 }
01317 }
01318
01319 }
01320
01321
01322
01323
01324
01325
01326
01327 LLLocalSpeakerMgr::LLLocalSpeakerMgr() : LLSpeakerMgr(LLVoiceChannelProximal::getInstance())
01328 {
01329 }
01330
01331 LLLocalSpeakerMgr::~LLLocalSpeakerMgr ()
01332 {
01333 }
01334
01335 void LLLocalSpeakerMgr::updateSpeakerList()
01336 {
01337
01338 LLSpeakerMgr::updateSpeakerList();
01339
01340
01341 std::vector< LLCharacter* >::iterator avatar_it;
01342 for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it)
01343 {
01344 LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it;
01345 if (dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) <= CHAT_NORMAL_RADIUS)
01346 {
01347 setSpeaker(avatarp->getID());
01348 }
01349 }
01350
01351
01352 for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
01353 {
01354 LLUUID speaker_id = speaker_it->first;
01355 LLSpeaker* speakerp = speaker_it->second;
01356 if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
01357 {
01358 LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
01359 if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
01360 {
01361 speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
01362 speakerp->mDotColor = INACTIVE_COLOR;
01363 speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
01364 }
01365 }
01366 }
01367 }