summaryrefslogtreecommitdiff
path: root/indra/newview/llcallfloater.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llcallfloater.cpp')
-rw-r--r--indra/newview/llcallfloater.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
new file mode 100644
index 0000000000..ad59c780f3
--- /dev/null
+++ b/indra/newview/llcallfloater.cpp
@@ -0,0 +1,275 @@
+/**
+ * @file llcallfloater.cpp
+ * @author Mike Antipov
+ * @brief Voice Control Panel in a Voice Chats (P2P, Group, Nearby...).
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llcallfloater.h"
+
+#include "llagentdata.h" // for gAgentID
+#include "llavatarlist.h"
+#include "llbottomtray.h"
+#include "llparticipantlist.h"
+#include "llspeakers.h"
+
+
+class LLNonAvatarCaller : public LLAvatarListItem
+{
+public:
+ LLNonAvatarCaller() : LLAvatarListItem(false)
+ {
+
+ }
+ BOOL postBuild()
+ {
+ BOOL rv = LLAvatarListItem::postBuild();
+
+ if (rv)
+ {
+ setOnline(true);
+ showLastInteractionTime(false);
+ setShowProfileBtn(false);
+ setShowInfoBtn(false);
+ }
+ return rv;
+ }
+
+ void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
+};
+
+
+static void* create_non_avatar_caller(void*)
+{
+ return new LLNonAvatarCaller;
+}
+
+LLCallFloater::LLCallFloater(const LLSD& key)
+: LLDockableFloater(NULL, key)
+, mSpeakerManager(NULL)
+, mPaticipants(NULL)
+, mAvatarList(NULL)
+, mNonAvatarCaller(NULL)
+, mVoiceType(VC_LOCAL_CHAT)
+{
+ mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
+}
+
+LLCallFloater::~LLCallFloater()
+{
+ mChannelChangedConnection.disconnect();
+ delete mPaticipants;
+ mPaticipants = NULL;
+}
+
+// virtual
+BOOL LLCallFloater::postBuild()
+{
+ LLDockableFloater::postBuild();
+ mAvatarList = getChild<LLAvatarList>("speakers_list");
+ childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
+
+ mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
+
+ LLView *anchor_panel = LLBottomTray::getInstance()->getChild<LLView>("speak_panel");
+
+ setDockControl(new LLDockControl(
+ anchor_panel, this,
+ getDockTongue(), LLDockControl::TOP));
+
+ initAgentData();
+
+ // update list for current session
+ updateSession();
+
+ // subscribe to to be notified Voice Channel is changed
+ mChannelChangedConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::onCurrentChannelChanged, this, _1));
+ return TRUE;
+}
+
+// virtual
+void LLCallFloater::onOpen(const LLSD& /*key*/)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+
+void LLCallFloater::leaveCall()
+{
+ LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice_channel && voice_channel->isActive())
+ {
+ voice_channel->deactivate();
+ }
+}
+
+void LLCallFloater::updateSession()
+{
+ LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice_channel)
+ {
+ lldebugs << "Current voice channel: " << voice_channel->getSessionID() << llendl;
+
+ if (mSpeakerManager && voice_channel->getSessionID() == mSpeakerManager->getSessionID())
+ {
+ lldebugs << "Speaker manager is already set for session: " << voice_channel->getSessionID() << llendl;
+ return;
+ }
+ else
+ {
+ mSpeakerManager = NULL;
+ }
+ }
+
+ const LLUUID& session_id = voice_channel->getSessionID();
+ lldebugs << "Set speaker manager for session: " << session_id << llendl;
+
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (im_session)
+ {
+ mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ switch (im_session->mType)
+ {
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
+ mVoiceType = VC_PEER_TO_PEER;
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ mVoiceType = VC_AD_HOC_CHAT;
+ break;
+ default:
+ mVoiceType = VC_GROUP_CHAT;
+ break;
+ }
+ }
+
+ if (NULL == mSpeakerManager)
+ {
+ // by default let show nearby chat participants
+ mSpeakerManager = LLLocalSpeakerMgr::getInstance();
+ lldebugs << "Set DEFAULT speaker manager" << llendl;
+ mVoiceType = VC_LOCAL_CHAT;
+ }
+
+ updateTitle();
+
+ //hide "Leave Call" button for nearby chat
+ bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
+ childSetVisible("leave_btn_panel", !is_local_chat);
+
+ refreshPartisipantList();
+}
+
+void LLCallFloater::refreshPartisipantList()
+{
+ delete mPaticipants;
+ mPaticipants = NULL;
+ mAvatarList->clear();
+
+ bool non_avatar_caller = false;
+ if (VC_PEER_TO_PEER == mVoiceType)
+ {
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSpeakerManager->getSessionID());
+ non_avatar_caller = !session->mOtherParticipantIsAvatar;
+ if (non_avatar_caller)
+ {
+ mNonAvatarCaller->setSpeakerId(session->mOtherParticipantID);
+ mNonAvatarCaller->setName(session->mName);
+ }
+ }
+
+ mNonAvatarCaller->setVisible(non_avatar_caller);
+ mAvatarList->setVisible(!non_avatar_caller);
+
+ if (!non_avatar_caller)
+ {
+ bool do_not_use_context_menu_in_local_chat = LLLocalSpeakerMgr::getInstance() != mSpeakerManager;
+ mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, do_not_use_context_menu_in_local_chat);
+
+ if (!do_not_use_context_menu_in_local_chat)
+ {
+ mAvatarList->setNoItemsCommentText(getString("no_one_near"));
+ }
+ }
+}
+
+void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/)
+{
+ // Forget speaker manager from the previous session to avoid using it after session was destroyed.
+ mSpeakerManager = NULL;
+ updateSession();
+}
+
+void LLCallFloater::updateTitle()
+{
+ LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ std::string title;
+ switch (mVoiceType)
+ {
+ case VC_LOCAL_CHAT:
+ title = getString("title_nearby");
+ break;
+ case VC_PEER_TO_PEER:
+ {
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = voice_channel->getSessionName();
+ title = getString("title_peer_2_peer", args);
+ }
+ break;
+ case VC_AD_HOC_CHAT:
+ title = getString("title_adhoc");
+ break;
+ case VC_GROUP_CHAT:
+ {
+ LLStringUtil::format_map_t args;
+ args["[GROUP]"] = voice_channel->getSessionName();
+ title = getString("title_group", args);
+ }
+ break;
+ }
+
+ setTitle(title);
+}
+
+void LLCallFloater::initAgentData()
+{
+ childSetValue("user_icon", gAgentID);
+
+ std::string name;
+ gCacheName->getFullName(gAgentID, name);
+ childSetValue("user_text", name);
+
+ LLOutputMonitorCtrl* speaking_indicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
+ speaking_indicator->setSpeakerId(gAgentID);
+}
+//EOF