From 0f61c00218a07a7d487e33256382c4a10561e0c1 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Mon, 22 Feb 2010 16:50:46 +0000
Subject: Enumerate available voice fonts.

---
 indra/newview/llvoiceclient.cpp | 124 ++++++++++++++++++++++++++++++++++++++++
 indra/newview/llvoiceclient.h   |  38 ++++++++++--
 2 files changed, 158 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 59606f17b2..92dfa6d30e 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -240,6 +240,12 @@ protected:
 	std::string		audioMediaString;
 	std::string		displayNameString;
 	std::string		deviceString;
+	std::string		idString;
+	std::string		descriptionString;
+	std::string		expirationDateString;
+	bool			hasExpired;
+	std::string		fontTypeString;
+	std::string		fontStatusString;
 	int				participantType;
 	bool			isLocallyMuted;
 	bool			isModeratorMuted;
@@ -625,6 +631,34 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 			autoAcceptMask = string;
 		else if (!stricmp("AutoAddAsBuddy", tag))
 			autoAddAsBuddy = string;
+		else if (!stricmp("SessionFont", tag))
+		{
+			gVoiceClient->addSessionFont(idString, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString);
+		}
+		else if (!stricmp("ID", tag))
+		{
+			idString = string;
+		}
+		else if (!stricmp("Description", tag))
+		{
+			descriptionString = string;
+		}
+		else if (!stricmp("ExpirationDate", tag))
+		{
+			expirationDateString = string;
+		}
+		else if (!stricmp("Expired", tag))
+		{
+			hasExpired = !stricmp(string.c_str(), "1");
+		}
+		else if (!stricmp("Type", tag))
+		{
+			fontTypeString = string;
+		}
+		else if (!stricmp("Status", tag))
+		{
+			fontStatusString = string;
+		}
 		else if (!stricmp("MessageHeader", tag))
 			messageHeader = string;
 		else if (!stricmp("MessageBody", tag))
@@ -895,6 +929,10 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		{
 			gVoiceClient->accountListAutoAcceptRulesResponse(statusCode, statusString);						
 		}
+		else if (!stricmp(actionCstr, "Account.GetSessionFonts.1"))
+		{
+			gVoiceClient->accountGetSessionFontsResponse(statusCode, statusString);
+		}
 		else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
 		{
 			// We don't need to process these, but they're so spammy we don't want to log them.
@@ -1243,6 +1281,9 @@ LLVoiceClient::LLVoiceClient() :
 	mBuddyListMapPopulated(false),
 	mBlockRulesListReceived(false),
 	mAutoAcceptRulesListReceived(false),
+
+	mSessionFontsReceived(false),
+
 	mCaptureDeviceDirty(false),
 	mRenderDeviceDirty(false),
 	mSpatialCoordsDirty(false),
@@ -2156,6 +2197,9 @@ void LLVoiceClient::stateMachine()
 
 			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
 
+			// request the set of available voice fonts
+			accountGetSessionFontsSendMessage();
+
 			// request the current set of block rules (we'll need them when updating the friends list)
 			accountListBlockRulesSendMessage();
 			
@@ -2641,6 +2685,24 @@ void LLVoiceClient::accountListAutoAcceptRulesSendMessage()
 	}
 }
 
+void LLVoiceClient::accountGetSessionFontsSendMessage()
+{
+	if(!mAccountHandle.empty())
+	{
+		std::ostringstream stream;
+
+		LL_DEBUGS("Voice") << "requesting session font list" << LL_ENDL;
+
+		stream
+		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.GetSessionFonts.1\">"
+			<< "<AccountHandle>" << mAccountHandle << "</AccountHandle>"
+		<< "</Request>"
+		<< "\n\n\n";
+
+		writeString(stream.str());
+	}
+}
+
 void LLVoiceClient::sessionGroupCreateSendMessage()
 {
 	if(!mAccountHandle.empty())
@@ -2691,6 +2753,7 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu
 	stream
 		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
 		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
+//	    << "<VoiceFontID>0</VoiceFontID>"
 		<< "<Name>" << mChannelName << "</Name>"
 	<< "</Request>\n\n\n";
 	writeString(stream.str());
@@ -2766,6 +2829,21 @@ void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
 	writeString(stream.str());
 }
 
+void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId)
+{
+	LL_DEBUGS("Voice") << "selecting voice font: " << fontId << " in session handle: " << session->mHandle << LL_ENDL;
+
+	std::ostringstream stream;
+
+	stream
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextConnect.1\">"
+		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+		<< "<SessionFontID>" << fontId << "</SessionFontID>"
+	<< "</Request>\n\n\n";
+
+	writeString(stream.str());
+}
+
 void LLVoiceClient::sessionTerminate()
 {
 	mSessionTerminateRequested = true;
@@ -6958,6 +7036,46 @@ void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const s
 	}
 }
 
+LLVoiceClient::voiceFontEntry::voiceFontEntry(const std::string &id) :
+	mID(id),
+	mHasExpired(false)
+{
+}
+
+LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string &id,
+															 const std::string &name,
+															 const std::string &description,
+															 const std::string &expirationDate,
+															 const bool hasExpired,
+															 const std::string &fontType,
+															 const std::string &fontStatus)
+{
+	voiceFontEntry *font = NULL;
+
+	voiceFontMap::iterator iter = mSessionFontMap.find(&id);
+	if(iter != mSessionFontMap.end())
+	{
+		// Found session font already in the map.
+		LL_DEBUGS("Voice") << "existing session font " << id << " : " << name << LL_ENDL;
+		font = iter->second;
+	}
+
+	if(font == NULL)
+	{
+		LL_DEBUGS("Voice") << "adding session font " << id << " : " << name << (hasExpired?" (Expired)":"") << LL_ENDL;
+		font = new voiceFontEntry(id);
+		font->mName = name;
+		font->mDescription = description;
+		font->mExpirationDate = expirationDate;
+		font->mHasExpired = hasExpired;
+		font->mFontType = fontType;
+		font->mFontStatus = fontStatus;
+
+		mSessionFontMap.insert(voiceFontMap::value_type(&(font->mID), font));
+	}
+	return font;
+}
+
 void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
 {
 	// Block list entries were updated via addBlockRule() during parsing.  Just flag that we're done.
@@ -6970,6 +7088,12 @@ void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std
 	mAutoAcceptRulesListReceived = true;
 }
 
+void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString)
+{
+	// Session font list entries were updated via addSessionFont() during parsing.  Just flag that we're done.
+	mSessionFontsReceived = true;
+}
+
 void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
 {
 	mParticipantObservers.insert(observer);
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index a96cf18e27..05624bcefd 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -424,8 +424,32 @@ static	void updatePosition(void);
 		void deleteAllAutoAcceptRules(void);
 		void addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy);
 		void accountListBlockRulesResponse(int statusCode, const std::string &statusString);						
-		void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);						
-		
+		void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);
+
+		struct voiceFontEntry
+		{
+			voiceFontEntry(const std::string &id);
+			// *TODO: Decide which of these we don't need to store
+			std::string mID;
+			std::string mName;
+			std::string mDescription;
+			std::string mExpirationDate;
+			bool		mHasExpired;
+			std::string mFontType;
+			std::string mFontStatus;
+		};
+
+		typedef std::map<const std::string*, voiceFontEntry*, stringMapComparitor> voiceFontMap;
+
+		voiceFontEntry *addSessionFont(const std::string &id,
+									   const std::string &name,
+									   const std::string &description,
+									   const std::string &expirationDate,
+									   const bool hasExpired,
+									   const std::string &fontType,
+									   const std::string &fontStatus);
+		void accountGetSessionFontsResponse(int statusCode, const std::string &statusString);
+
 		/////////////////////////////
 		// session control messages
 		void connectorCreate();
@@ -447,12 +471,15 @@ static	void updatePosition(void);
 
 		void accountListBlockRulesSendMessage();
 		void accountListAutoAcceptRulesSendMessage();
-		
+
+		void accountGetSessionFontsSendMessage();
+
 		void sessionGroupCreateSendMessage();
 		void sessionCreateSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
 		void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
 		void sessionMediaConnectSendMessage(sessionState *session);		// just joins the audio session
 		void sessionTextConnectSendMessage(sessionState *session);		// just joins the text session
+		void sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId);
 		void sessionTerminateSendMessage(sessionState *session);
 		void sessionGroupTerminateSendMessage(sessionState *session);
 		void sessionMediaDisconnectSendMessage(sessionState *session);
@@ -653,7 +680,10 @@ static	void updatePosition(void);
 		bool mBlockRulesListReceived;
 		bool mAutoAcceptRulesListReceived;
 		buddyListMap mBuddyListMap;
-		
+
+		bool mSessionFontsReceived;
+		voiceFontMap mSessionFontMap;
+
 		deviceList mCaptureDevices;
 		deviceList mRenderDevices;
 
-- 
cgit v1.2.3


From 5518e15f89359ba1627633f59f7299b69fc2bd69 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Mon, 22 Feb 2010 16:52:23 +0000
Subject: Added stateFontListReceived to the voice client state machine. This
 makes sure we have the voice font list before attempting to start a session.

---
 indra/newview/llvoiceclient.cpp | 11 +++++++++++
 indra/newview/llvoiceclient.h   |  2 +-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 92dfa6d30e..de4e53f52c 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -1622,6 +1622,7 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
 		CASE(stateNeedsLogin);
 		CASE(stateLoggingIn);
 		CASE(stateLoggedIn);
+		CASE(stateFontListReceived);
 		CASE(stateCreatingSessionGroup);
 		CASE(stateNoChannel);
 		CASE(stateJoiningSession);
@@ -2231,6 +2232,11 @@ void LLVoiceClient::stateMachine()
 					writeString(stream.str());
 				}
 			}
+
+			// accountGetSessionFontsResponse() will transition from here to stateFontListReceived.
+
+		//MARK: stateFontListReceived
+		case stateFontListReceived:		// font list received
 			
 #if USE_SESSION_GROUPS			
 			// create the main session group
@@ -7092,6 +7098,11 @@ void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::st
 {
 	// Session font list entries were updated via addSessionFont() during parsing.  Just flag that we're done.
 	mSessionFontsReceived = true;
+
+	if(getState() == stateLoggedIn)
+	{
+		setState(stateFontListReceived);
+	}
 }
 
 void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 05624bcefd..2d8fff5508 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -429,7 +429,6 @@ static	void updatePosition(void);
 		struct voiceFontEntry
 		{
 			voiceFontEntry(const std::string &id);
-			// *TODO: Decide which of these we don't need to store
 			std::string mID;
 			std::string mName;
 			std::string mDescription;
@@ -584,6 +583,7 @@ static	void updatePosition(void);
 			stateNeedsLogin,			// send login request
 			stateLoggingIn,				// waiting for account handle
 			stateLoggedIn,				// account handle received
+			stateFontListReceived,		// List of available voice fonts received
 			stateCreatingSessionGroup,	// Creating the main session group
 			stateNoChannel,				// 
 			stateJoiningSession,		// waiting for session handle
-- 
cgit v1.2.3


From 9f9b240dcee53a50b56a0ccb8d255a86d0ce62c9 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Tue, 6 Apr 2010 11:39:01 +0100
Subject: Added voice font selection to the voice floater.

---
 indra/newview/app_settings/logcontrol.xml          |  1 +
 indra/newview/llcallfloater.cpp                    | 53 ++++++++++++++--
 indra/newview/llcallfloater.h                      | 21 ++++---
 indra/newview/llvoiceclient.cpp                    | 73 +++++++++++++++++-----
 indra/newview/llvoiceclient.h                      | 23 ++++---
 .../default/xui/en/floater_voice_controls.xml      | 38 ++++++++++-
 6 files changed, 173 insertions(+), 36 deletions(-)

diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index d7bb64ce8a..d3fb958638 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -40,6 +40,7 @@
 						</array>
 					<key>tags</key>
 						<array>
+							<string>Voice</string>
 						</array>
 				</map>
 			</array>
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 76e058a1c3..52739184c0 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -52,6 +52,7 @@
 #include "lltransientfloatermgr.h"
 #include "llviewerwindow.h"
 #include "llvoicechannel.h"
+#include "llvoiceclient.h" // for Voice font list types
 #include "llviewerparcelmgr.h"
 
 static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);
@@ -95,7 +96,7 @@ static void* create_non_avatar_caller(void*)
 	return new LLNonAvatarCaller;
 }
 
-LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL;
+LLVoiceChannel* LLCallFloater::sCurrentVoiceChannel = NULL;
 
 LLCallFloater::LLCallFloater(const LLSD& key)
 : LLTransientDockableFloater(NULL, false, key)
@@ -105,6 +106,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
 , mNonAvatarCaller(NULL)
 , mVoiceType(VC_LOCAL_CHAT)
 , mAgentPanel(NULL)
+, mVoiceFont(NULL)
 , mSpeakingIndicator(NULL)
 , mIsModeratorMutedVoice(false)
 , mInitParticipantsVoiceState(false)
@@ -146,6 +148,9 @@ BOOL LLCallFloater::postBuild()
 
 	childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
 
+	mVoiceFont = getChild<LLComboBox>("voice_font");
+	childSetCommitCallback("voice_font", commitVoiceFont, this); // *FIX: childSetCommitCallback deprecated
+
 	mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
 	mNonAvatarCaller->setVisible(FALSE);
 
@@ -157,7 +162,6 @@ BOOL LLCallFloater::postBuild()
 
 	initAgentData();
 
-
 	connectToChannel(LLVoiceChannel::getCurrentVoiceChannel());
 
 	setIsChrome(true);
@@ -205,6 +209,9 @@ void LLCallFloater::draw()
 // virtual
 void LLCallFloater::onChange()
 {
+	// *FIX: Temporarily dumping this here till I decide where it should go
+	updateVoiceFont();
+
 	if (NULL == mParticipants) return;
 
 	updateParticipantsVoiceState();
@@ -231,6 +238,37 @@ void LLCallFloater::leaveCall()
 	}
 }
 
+/* static */
+void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata)
+{
+	LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue());
+}
+
+void LLCallFloater::updateVoiceFont()
+{
+	if (mVoiceFont)
+	{
+		mVoiceFont->removeall();
+		mVoiceFont->add(getString("no_voice_font"), 0);
+
+		if (LLVoiceClient::getInstance()->getVoiceFontsAvailable())
+		{
+			const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::getInstance()->getVoiceFontList();
+
+			for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it)
+			{
+				mVoiceFont->add(*(it->second), it->first, ADD_BOTTOM);
+			}
+			mVoiceFont->setEnabled(true);
+			mVoiceFont->setValue(LLVoiceClient::getInstance()->getVoiceFont());
+		}
+		else
+		{
+			mVoiceFont->setEnabled(false);
+		}
+	}
+}
+
 void LLCallFloater::updateSession()
 {
 	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
@@ -369,7 +407,7 @@ void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
 	// *NOTE: if signal was sent for voice channel with LLVoiceChannel::STATE_NO_CHANNEL_INFO
 	// it sill be sent for the same channel again (when state is changed).
 	// So, lets ignore this call.
-	if (channel == sCurrentVoiceCanel) return;
+	if (channel == sCurrentVoiceChannel) return;
 
 	LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls");
 
@@ -714,9 +752,9 @@ void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
 {
 	mVoiceChannelStateChangeConnection.disconnect();
 
-	sCurrentVoiceCanel = channel;
+	sCurrentVoiceChannel = channel;
 
-	mVoiceChannelStateChangeConnection = sCurrentVoiceCanel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2));
+	mVoiceChannelStateChangeConnection = sCurrentVoiceChannel->setStateChangedCallback(boost::bind(&LLCallFloater::onVoiceChannelStateChanged, this, _1, _2));
 
 	updateState(channel->getState());
 }
@@ -736,7 +774,7 @@ void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old
 
 void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
 {
-	LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceCanel->getSessionName() << LL_ENDL;
+	LL_DEBUGS("Voice") << "Updating state: " << new_state << ", session name: " << sCurrentVoiceChannel->getSessionName() << LL_ENDL;
 	if (LLVoiceChannel::STATE_CONNECTED == new_state)
 	{
 		updateSession();
@@ -745,6 +783,9 @@ void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
 	{
 		reset(new_state);
 	}
+
+	// *FIX: Dumped here till I decide where to put it
+	updateVoiceFont();
 }
 
 void LLCallFloater::reset(const LLVoiceChannel::EState& new_state)
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 0a8ea7de39..9a13d853c9 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -40,6 +40,7 @@
 
 class LLAvatarList;
 class LLAvatarListItem;
+class LLComboBox;
 class LLNonAvatarCaller;
 class LLOutputMonitorCtrl;
 class LLParticipantList;
@@ -47,15 +48,15 @@ class LLSpeakerMgr;
 class LLSpeakersDelayActionsStorage;
 
 /**
- * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button.
- * It can be torn-off and freely positioned onscreen.
+ * The Voice Control Panel is an ambient window summoned by clicking the flyout chevron
+ * on the Speak button. It can be torn-off and freely positioned onscreen.
  *
- * When the Resident is engaged in Nearby Voice Chat, the Voice Control Panel provides control over 
- * the Resident's own microphone input volume, the audible volume of each of the other participants,
- * the Resident's own Voice Morphing settings (if she has subscribed to enable the feature), and Voice Recording.
+ * When the Resident is engaged in Voice Chat, the Voice Control Panel provides control
+ * over the audible volume of each of the other participants, the Resident's own Voice
+ * Morphing settings (if she has subscribed to enable the feature), and Voice Recording.
  *
- * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel also provides an 
- * 'Leave Call' button to allow the Resident to leave that voice channel.
+ * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel
+ * also provides a 'Leave Call' button to allow the Resident to leave that voice channel.
  */
 class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver
 {
@@ -101,6 +102,9 @@ private:
 
 	void leaveCall();
 
+	static void commitVoiceFont(LLUICtrl*,void* userdata);
+	void updateVoiceFont();
+
 	/**
 	 * Updates mSpeakerManager and list according to current Voice Channel
 	 *
@@ -230,6 +234,7 @@ private:
 	LLNonAvatarCaller* mNonAvatarCaller;
 	EVoiceControls mVoiceType;
 	LLPanel* mAgentPanel;
+	LLComboBox* mVoiceFont;
 	LLOutputMonitorCtrl* mSpeakingIndicator;
 	bool mIsModeratorMutedVoice;
 
@@ -259,7 +264,7 @@ private:
 	 *
 	 * @see sOnCurrentChannelChanged()
 	 */
-	static LLVoiceChannel* sCurrentVoiceCanel;
+	static LLVoiceChannel* sCurrentVoiceChannel;
 
 	/* virtual */
 	LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index de4e53f52c..5502744882 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -240,7 +240,7 @@ protected:
 	std::string		audioMediaString;
 	std::string		displayNameString;
 	std::string		deviceString;
-	std::string		idString;
+	S32				id;
 	std::string		descriptionString;
 	std::string		expirationDateString;
 	bool			hasExpired;
@@ -503,7 +503,20 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
 			{
 				gVoiceClient->deleteAllAutoAcceptRules();
 			}
-			
+			else if (!stricmp("SessionFonts", tag))
+			{
+				LLVoiceClient::getInstance()->clearSessionFonts();
+			}
+			else if (!stricmp("SessionFont", tag))
+			{
+				id = 0;
+				nameString.clear();
+				descriptionString.clear();
+				expirationDateString.clear();
+				hasExpired.clear();
+				fontTypeString.clear();
+				fontStatusString.clear();
+			}
 		}
 	}
 	responseDepth++;
@@ -633,11 +646,11 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 			autoAddAsBuddy = string;
 		else if (!stricmp("SessionFont", tag))
 		{
-			gVoiceClient->addSessionFont(idString, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString);
+			LLVoiceClient::getInstance()->addSessionFont(id, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString);
 		}
 		else if (!stricmp("ID", tag))
 		{
-			idString = string;
+			id = strtol(string.c_str(), NULL, 10);
 		}
 		else if (!stricmp("Description", tag))
 		{
@@ -860,6 +873,8 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		}
 		else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))  
 		{
+			// *TODO: Receive the current SessionFontID?
+			
 			/*
 			<Event type="SessionUpdatedEvent">
 				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
@@ -931,7 +946,7 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		}
 		else if (!stricmp(actionCstr, "Account.GetSessionFonts.1"))
 		{
-			gVoiceClient->accountGetSessionFontsResponse(statusCode, statusString);
+			LLVoiceClient::getInstance()->accountGetSessionFontsResponse(statusCode, statusString);
 		}
 		else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
 		{
@@ -1283,6 +1298,7 @@ LLVoiceClient::LLVoiceClient() :
 	mAutoAcceptRulesListReceived(false),
 
 	mSessionFontsReceived(false),
+	mFontID(0),
 
 	mCaptureDeviceDirty(false),
 	mRenderDeviceDirty(false),
@@ -2759,7 +2775,7 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu
 	stream
 		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
 		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
-//	    << "<VoiceFontID>0</VoiceFontID>"
+		<< "<VoiceFontID>" << mFontID << "</VoiceFontID>"
 		<< "<Name>" << mChannelName << "</Name>"
 	<< "</Request>\n\n\n";
 	writeString(stream.str());
@@ -2835,16 +2851,17 @@ void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
 	writeString(stream.str());
 }
 
-void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId)
+void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session)
 {
-	LL_DEBUGS("Voice") << "selecting voice font: " << fontId << " in session handle: " << session->mHandle << LL_ENDL;
+	llassert(session);
+	LL_DEBUGS("Voice") << "requesting voice font: " << mFontID << " in session handle: " << session->mHandle << LL_ENDL;
 
 	std::ostringstream stream;
 
 	stream
-	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.TextConnect.1\">"
+	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetVoiceFont.1\">"
 		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-		<< "<SessionFontID>" << fontId << "</SessionFontID>"
+		<< "<SessionFontID>" << mFontID << "</SessionFontID>"
 	<< "</Request>\n\n\n";
 
 	writeString(stream.str());
@@ -7042,13 +7059,13 @@ void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const s
 	}
 }
 
-LLVoiceClient::voiceFontEntry::voiceFontEntry(const std::string &id) :
+LLVoiceClient::voiceFontEntry::voiceFontEntry(S32 id) :
 	mID(id),
 	mHasExpired(false)
 {
 }
 
-LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string &id,
+LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const voice_font_id_t &id,
 															 const std::string &name,
 															 const std::string &description,
 															 const std::string &expirationDate,
@@ -7058,7 +7075,7 @@ LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string &
 {
 	voiceFontEntry *font = NULL;
 
-	voiceFontMap::iterator iter = mSessionFontMap.find(&id);
+	voice_font_map_t::iterator iter = mSessionFontMap.find(id);
 	if(iter != mSessionFontMap.end())
 	{
 		// Found session font already in the map.
@@ -7077,11 +7094,39 @@ LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const std::string &
 		font->mFontType = fontType;
 		font->mFontStatus = fontStatus;
 
-		mSessionFontMap.insert(voiceFontMap::value_type(&(font->mID), font));
+		mSessionFontList.insert(voice_font_list_t::value_type(font->mID, &(font->mName)));
+		mSessionFontMap.insert(voice_font_map_t::value_type(font->mID, font));
 	}
 	return font;
 }
 
+bool LLVoiceClient::setVoiceFont(voice_font_id_t id)
+{
+	if (!mAudioSession || !mAudioSession->mVoiceEnabled || !mSessionFontsReceived)
+	{
+		LL_DEBUGS("Voice") << "Session fonts not available" << LL_ENDL;
+		return false;
+	}
+
+	if(id == 0 || mSessionFontMap.find(id) != mSessionFontMap.end())
+	{
+		mFontID = id;
+	}
+	else
+	{
+		LL_DEBUGS("Voice") << "Invalid session font " << id << LL_ENDL;
+		return false;
+	}
+
+	sessionSetVoiceFontSendMessage(mAudioSession);
+	return true;
+}
+
+const LLVoiceClient::voice_font_id_t LLVoiceClient::getVoiceFont() const
+{
+	return mFontID;
+}
+
 void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
 {
 	// Block list entries were updated via addBlockRule() during parsing.  Just flag that we're done.
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 2d8fff5508..05e9dcc896 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -428,8 +428,8 @@ static	void updatePosition(void);
 
 		struct voiceFontEntry
 		{
-			voiceFontEntry(const std::string &id);
-			std::string mID;
+			voiceFontEntry(S32 id);
+			S32			mID;
 			std::string mName;
 			std::string mDescription;
 			std::string mExpirationDate;
@@ -438,9 +438,16 @@ static	void updatePosition(void);
 			std::string mFontStatus;
 		};
 
-		typedef std::map<const std::string*, voiceFontEntry*, stringMapComparitor> voiceFontMap;
+		typedef S32 voice_font_id_t;
+		typedef std::map<voice_font_id_t, std::string*> voice_font_list_t;
+		typedef std::map<voice_font_id_t, voiceFontEntry*> voice_font_map_t;
 
-		voiceFontEntry *addSessionFont(const std::string &id,
+		bool getVoiceFontsAvailable() const { return mSessionFontsReceived; };
+		bool setVoiceFont(voice_font_id_t id);
+		const voice_font_id_t getVoiceFont() const;
+		const voice_font_list_t &getVoiceFontList() const { return mSessionFontList; };
+
+		voiceFontEntry *addSessionFont(const voice_font_id_t &id,
 									   const std::string &name,
 									   const std::string &description,
 									   const std::string &expirationDate,
@@ -478,7 +485,7 @@ static	void updatePosition(void);
 		void sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio = true, bool startText = false);
 		void sessionMediaConnectSendMessage(sessionState *session);		// just joins the audio session
 		void sessionTextConnectSendMessage(sessionState *session);		// just joins the text session
-		void sessionSetVoiceFontSendMessage(sessionState *session, const std::string &fontId);
+		void sessionSetVoiceFontSendMessage(sessionState *session);
 		void sessionTerminateSendMessage(sessionState *session);
 		void sessionGroupTerminateSendMessage(sessionState *session);
 		void sessionMediaDisconnectSendMessage(sessionState *session);
@@ -510,7 +517,7 @@ static	void updatePosition(void);
 
 		deviceList *getCaptureDevices();
 		deviceList *getRenderDevices();
-		
+
 		void setNonSpatialChannel(
 			const std::string &uri,
 			const std::string &credentials);
@@ -682,7 +689,9 @@ static	void updatePosition(void);
 		buddyListMap mBuddyListMap;
 
 		bool mSessionFontsReceived;
-		voiceFontMap mSessionFontMap;
+		S32 mFontID;
+		voice_font_list_t mSessionFontList;
+		voice_font_map_t mSessionFontMap; // *TODO: make private
 
 		deviceList mCaptureDevices;
 		deviceList mRenderDevices;
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index c4411db8c5..100a060557 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -33,6 +33,9 @@
      name="no_one_near">
         No one near has voice enabled
     </string>
+    <floater.string name="no_voice_font">
+        No Voice Effect
+    </floater.string>
       <layout_stack
          clip="false"
          follows="all"
@@ -84,7 +87,39 @@
              visible="true"
              width="20" />
         </layout_panel>
-         <layout_panel
+        <layout_stack
+         clip="false"
+         auto_resize="false"
+         follows="left|right"
+         height="23"
+         layout="topleft"
+         left="10"
+         mouse_opaque="false"
+         name="voice_font_and_leave_call_stack"
+         orientation="horizontal"
+         width="263">
+          <layout_panel
+           auto_resize="false"
+           user_resize="false"
+           follows="top|left"
+           height="26"
+           visible="true"
+           layout="topleft"
+           name="voice_font_panel"
+           width="120">
+            <combo_box
+             follows="left|top"
+             height="23"
+             name="voice_font"
+             top_pad="0"
+             width="120">
+              <combo_box.item
+                label="No Voice Effect"
+                name="no_voice_font"
+                value="0" />
+            </combo_box>
+          </layout_panel>
+        <layout_panel
           auto_resize="false"
           user_resize="false" 
           follows="top|left"
@@ -101,6 +136,7 @@
             name="leave_call_btn"
             width="100" />
          </layout_panel>
+      </layout_stack>
       <layout_panel
           follows="all"
           layout="topleft"
-- 
cgit v1.2.3


From 5a8770c9e37ae3ebe6fca7f8a631be4179763aed Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Fri, 9 Apr 2010 01:29:03 +0100
Subject: Added a method to clear the session font list

---
 indra/newview/llvoiceclient.cpp | 25 ++++++++++++++++---------
 indra/newview/llvoiceclient.h   | 15 ++++++++-------
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 4ea4d9c16e..8fe734030f 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -527,7 +527,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
 				nameString.clear();
 				descriptionString.clear();
 				expirationDateString.clear();
-				hasExpired.clear();
+				hasExpired = false;
 				fontTypeString.clear();
 				fontStatusString.clear();
 			}
@@ -7157,13 +7157,21 @@ LLVoiceClient::voiceFontEntry::voiceFontEntry(S32 id) :
 {
 }
 
-LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const voice_font_id_t &id,
-															 const std::string &name,
-															 const std::string &description,
-															 const std::string &expirationDate,
-															 const bool hasExpired,
-															 const std::string &fontType,
-															 const std::string &fontStatus)
+void LLVoiceClient::clearSessionFonts()
+{
+	// *FIX: Currently set voice font will be invalid
+	mSessionFontsReceived = false;
+	mSessionFontList.clear();
+	mSessionFontMap.clear();
+}
+
+void LLVoiceClient::addSessionFont(const voice_font_id_t &id,
+								   const std::string &name,
+								   const std::string &description,
+								   const std::string &expirationDate,
+								   const bool hasExpired,
+								   const std::string &fontType,
+								   const std::string &fontStatus)
 {
 	voiceFontEntry *font = NULL;
 
@@ -7189,7 +7197,6 @@ LLVoiceClient::voiceFontEntry *LLVoiceClient::addSessionFont(const voice_font_id
 		mSessionFontList.insert(voice_font_list_t::value_type(font->mID, &(font->mName)));
 		mSessionFontMap.insert(voice_font_map_t::value_type(font->mID, font));
 	}
-	return font;
 }
 
 bool LLVoiceClient::setVoiceFont(voice_font_id_t id)
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 0df4e4bb3b..9409e19644 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -452,13 +452,14 @@ static	void updatePosition(void);
 		const voice_font_id_t getVoiceFont() const;
 		const voice_font_list_t &getVoiceFontList() const { return mSessionFontList; };
 
-		voiceFontEntry *addSessionFont(const voice_font_id_t &id,
-									   const std::string &name,
-									   const std::string &description,
-									   const std::string &expirationDate,
-									   const bool hasExpired,
-									   const std::string &fontType,
-									   const std::string &fontStatus);
+		void clearSessionFonts();
+		void addSessionFont(const voice_font_id_t &id,
+							const std::string &name,
+							const std::string &description,
+							const std::string &expirationDate,
+							const bool hasExpired,
+							const std::string &fontType,
+							const std::string &fontStatus);
 		void accountGetSessionFontsResponse(int statusCode, const std::string &statusString);
 
 		/////////////////////////////
-- 
cgit v1.2.3


From e9b613e8d4362412a03b8c141614553f902a24b3 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Mon, 19 Apr 2010 15:16:48 +0100
Subject: Identify fonts with UUIDs rather than using the font indexes directly
 as they are not guaranteed unique across sessions. Replaced all references to
 "Font" with "Voice Font" where possible to reduce confusion for anyone
 grepping code in future.

---
 indra/newview/llcallfloater.cpp  |   6 +-
 indra/newview/llvoicechannel.cpp |   6 +-
 indra/newview/llvoiceclient.cpp  | 253 ++++++++++++++++++++++++++-------------
 indra/newview/llvoiceclient.h    |  97 +++++++++------
 4 files changed, 241 insertions(+), 121 deletions(-)

diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index f13e74679d..30f211d46d 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -250,15 +250,15 @@ void LLCallFloater::updateVoiceFont()
 	if (mVoiceFont)
 	{
 		mVoiceFont->removeall();
-		mVoiceFont->add(getString("no_voice_font"), 0);
+		mVoiceFont->add(getString("no_voice_font"), LLUUID::null);
 
-		if (LLVoiceClient::getInstance()->getVoiceFontsAvailable())
+		if (LLVoiceClient::getInstance()->hasVoiceFonts())
 		{
 			const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::getInstance()->getVoiceFontList();
 
 			for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it)
 			{
-				mVoiceFont->add(*(it->second), it->first, ADD_BOTTOM);
+				mVoiceFont->add(*(it->first), *(it->second), ADD_BOTTOM);
 			}
 			mVoiceFont->setEnabled(true);
 			mVoiceFont->setValue(LLVoiceClient::getInstance()->getVoiceFont());
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 7bb1006e93..9ab0bf9552 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -887,9 +887,9 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s
 	else
 	{
 		LL_WARNS("Voice") << "incoming SIP URL is not provided. Channel may not work properly." << LL_ENDL;
-		// In case of incoming AvaLine call generated URI will be differ from original one.
-		// This is because Avatar-2-Avatar URI is based on avatar UUID but Avaline is not.
-		// See LLVoiceClient::sessionAddedEvent() -> setUUIDFromStringHash()
+		// In the case of an incoming AvaLine call, the generated URI will be different from the
+		// original one. This is because the P2P URI is based on avatar UUID but Avaline is not.
+		// See LLVoiceClient::sessionAddedEvent()
 		setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
 	}
 	
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 8fe734030f..00f0c70c17 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -73,15 +73,11 @@
 #include "llvoavatarself.h"
 #include "llvoicechannel.h"
 
+#include "stringize.h"
+
 // for base64 decoding
 #include "apr_base64.h"
 
-// for SHA1 hash
-#include "apr_sha1.h"
-
-// for MD5 hash
-#include "llmd5.h"
-
 #define USE_SESSION_GROUPS 0
 
 static bool sConnectingToAgni = false;
@@ -116,14 +112,6 @@ const int MAX_LOGIN_RETRIES = 12;
 // blocked is VERY rare and it's better to sacrifice response time in this situation for the sake of stability.
 const int MAX_NORMAL_JOINING_SPATIAL_NUM = 50;
 
-static void setUUIDFromStringHash(LLUUID &uuid, const std::string &str)
-{
-	LLMD5 md5_uuid;
-	md5_uuid.update((const unsigned char*)str.data(), str.size());
-	md5_uuid.finalize();
-	md5_uuid.raw_digest(uuid.mData);
-}
-
 static int scale_mic_volume(float volume)
 {
 	// incoming volume has the range [0.0 ... 2.0], with 1.0 as the default.
@@ -258,8 +246,8 @@ protected:
 	std::string		descriptionString;
 	std::string		expirationDateString;
 	bool			hasExpired;
-	std::string		fontTypeString;
-	std::string		fontStatusString;
+	S32				fontType;
+	S32				fontStatus;
 	int				participantType;
 	bool			isLocallyMuted;
 	bool			isModeratorMuted;
@@ -519,7 +507,7 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
 			}
 			else if (!stricmp("SessionFonts", tag))
 			{
-				LLVoiceClient::getInstance()->clearSessionFonts();
+				LLVoiceClient::getInstance()->deleteAllVoiceFonts();
 			}
 			else if (!stricmp("SessionFont", tag))
 			{
@@ -528,8 +516,8 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
 				descriptionString.clear();
 				expirationDateString.clear();
 				hasExpired = false;
-				fontTypeString.clear();
-				fontStatusString.clear();
+				fontType = 0;
+				fontStatus = 0;
 			}
 		}
 	}
@@ -660,7 +648,7 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 			autoAddAsBuddy = string;
 		else if (!stricmp("SessionFont", tag))
 		{
-			LLVoiceClient::getInstance()->addSessionFont(id, nameString, descriptionString, expirationDateString, hasExpired, fontTypeString, fontStatusString);
+			LLVoiceClient::getInstance()->addVoiceFont(id, nameString, descriptionString, expirationDateString, hasExpired, fontType, fontStatus);
 		}
 		else if (!stricmp("ID", tag))
 		{
@@ -680,11 +668,11 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
 		}
 		else if (!stricmp("Type", tag))
 		{
-			fontTypeString = string;
+			fontType = strtol(string.c_str(), NULL, 10);
 		}
 		else if (!stricmp("Status", tag))
 		{
-			fontStatusString = string;
+			fontStatus = strtol(string.c_str(), NULL, 10);
 		}
 		else if (!stricmp("MessageHeader", tag))
 			messageHeader = string;
@@ -887,8 +875,6 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		}
 		else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))  
 		{
-			// *TODO: Receive the current SessionFontID?
-			
 			/*
 			<Event type="SessionUpdatedEvent">
 				<SessionGroupHandle>c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0</SessionGroupHandle>
@@ -1391,9 +1377,6 @@ LLVoiceClient::LLVoiceClient() :
 	mBlockRulesListReceived(false),
 	mAutoAcceptRulesListReceived(false),
 
-	mSessionFontsReceived(false),
-	mFontID(0),
-
 	mCaptureDeviceDirty(false),
 	mRenderDeviceDirty(false),
 	mSpatialCoordsDirty(false),
@@ -1874,7 +1857,8 @@ void LLVoiceClient::stateMachine()
 			// Clean up and reset everything. 
 			closeSocket();
 			deleteAllSessions();
-			deleteAllBuddies();		
+			deleteAllBuddies();
+			deleteAllVoiceFonts();
 			
 			mConnectorHandle.clear();
 			mAccountHandle.clear();
@@ -2640,6 +2624,7 @@ void LLVoiceClient::stateMachine()
 			mAccountHandle.clear();
 			deleteAllSessions();
 			deleteAllBuddies();
+			deleteAllVoiceFonts();
 
 			if(mVoiceEnabled && !mRelogRequested)
 			{
@@ -2829,7 +2814,7 @@ void LLVoiceClient::accountGetSessionFontsSendMessage()
 	{
 		std::ostringstream stream;
 
-		LL_DEBUGS("Voice") << "requesting session font list" << LL_ENDL;
+		LL_DEBUGS("Voice") << "Requesting voice font list." << LL_ENDL;
 
 		stream
 		<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Account.GetSessionFonts.1\">"
@@ -2863,7 +2848,10 @@ void LLVoiceClient::sessionGroupCreateSendMessage()
 void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)
 {
 	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
-	
+
+	S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
+	LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL;
+
 	session->mCreateInProgress = true;
 	if(startAudio)
 	{
@@ -2887,11 +2875,11 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu
 			<< "<Password>" << LLURI::escape(session->mHash, allowed_chars) << "</Password>"
 			<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>";
 	}
-	
+
 	stream
 		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
 		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
-		<< "<VoiceFontID>" << mFontID << "</VoiceFontID>"
+		<< "<VoiceFontID>" << font_index << "</VoiceFontID>"
 		<< "<Name>" << mChannelName << "</Name>"
 	<< "</Request>\n\n\n";
 	writeString(stream.str());
@@ -2900,7 +2888,10 @@ void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAu
 void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)
 {
 	LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
-	
+
+	S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
+	LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL;
+
 	session->mCreateInProgress = true;
 	if(startAudio)
 	{
@@ -2926,6 +2917,7 @@ void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, boo
 		<< "<Name>" << mChannelName << "</Name>"
 		<< "<ConnectAudio>" << (startAudio?"true":"false") << "</ConnectAudio>"
 		<< "<ConnectText>" << (startText?"true":"false") << "</ConnectText>"
+		<< "<VoiceFontID>" << font_index << "</VoiceFontID>"
 		<< "<Password>" << password << "</Password>"
 		<< "<PasswordHashAlgorithm>SHA1UserName</PasswordHashAlgorithm>"
 	<< "</Request>\n\n\n"
@@ -2938,6 +2930,9 @@ void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
 {
 	LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL;
 
+	S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
+	LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << ")" << LL_ENDL;
+
 	session->mMediaConnectInProgress = true;
 	
 	std::ostringstream stream;
@@ -2946,6 +2941,7 @@ void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
 	<< "<Request requestId=\"" << session->mHandle << "\" action=\"Session.MediaConnect.1\">"
 		<< "<SessionGroupHandle>" << session->mGroupHandle << "</SessionGroupHandle>"
 		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
+		<< "<VoiceFontID>" << font_index << "</VoiceFontID>"
 		<< "<Media>Audio</Media>"
 	<< "</Request>\n\n\n";
 
@@ -2969,15 +2965,15 @@ void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
 
 void LLVoiceClient::sessionSetVoiceFontSendMessage(sessionState *session)
 {
-	llassert(session);
-	LL_DEBUGS("Voice") << "requesting voice font: " << mFontID << " in session handle: " << session->mHandle << LL_ENDL;
+	S32 font_index = getVoiceFontIndex(session->mVoiceFontID);
+	LL_DEBUGS("Voice") << "Requesting voice font: " << session->mVoiceFontID << " (" << font_index << "), session handle: " << session->mHandle << LL_ENDL;
 
 	std::ostringstream stream;
 
 	stream
 	<< "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Session.SetVoiceFont.1\">"
 		<< "<SessionHandle>" << session->mHandle << "</SessionHandle>"
-		<< "<SessionFontID>" << mFontID << "</SessionFontID>"
+		<< "<SessionFontID>" << font_index << "</SessionFontID>"
 	<< "</Request>\n\n\n";
 
 	writeString(stream.str());
@@ -4272,7 +4268,7 @@ void LLVoiceClient::sessionAddedEvent(
 			else
 			{
 				LL_INFOS("Voice") << "Could not generate caller id from uri, using hash of uri " << session->mSIPURI << LL_ENDL;
-				setUUIDFromStringHash(session->mCallerID, session->mSIPURI);
+				session->mCallerID.generate(session->mSIPURI);
 				session->mSynthesizedCallerID = true;
 				
 				// Can't look up the name in this case -- we have to extract it from the URI.
@@ -5252,7 +5248,7 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con
 			{
 				// Create a UUID by hashing the URI, but do NOT set mAvatarIDValid.
 				// This tells both code in LLVoiceClient and code in llfloateractivespeakers.cpp that the ID will not be in the name cache.
-				setUUIDFromStringHash(result->mAvatarID, uri);
+				result->mAvatarID.generate(uri);
 			}
 		}
 		
@@ -6637,7 +6633,8 @@ LLVoiceClient::sessionState::sessionState() :
 	mReconnect(false),
 	mVolumeDirty(false),
 	mMuteDirty(false),
-	mParticipantsChanged(false)
+	mParticipantsChanged(false),
+	mVoiceFontID(0)
 {
 }
 
@@ -7151,69 +7148,128 @@ void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const s
 	}
 }
 
-LLVoiceClient::voiceFontEntry::voiceFontEntry(S32 id) :
+LLVoiceClient::voiceFontEntry::voiceFontEntry(LLUUID& id) :
 	mID(id),
-	mHasExpired(false)
+	mFontIndex(0),
+	mHasExpired(false),
+	mFontType(VOICE_FONT_TYPE_NONE),
+	mFontStatus(VOICE_FONT_STATUS_NONE)
 {
 }
 
-void LLVoiceClient::clearSessionFonts()
+LLVoiceClient::voiceFontEntry::~voiceFontEntry()
 {
-	// *FIX: Currently set voice font will be invalid
-	mSessionFontsReceived = false;
-	mSessionFontList.clear();
-	mSessionFontMap.clear();
 }
 
-void LLVoiceClient::addSessionFont(const voice_font_id_t &id,
-								   const std::string &name,
-								   const std::string &description,
-								   const std::string &expirationDate,
-								   const bool hasExpired,
-								   const std::string &fontType,
-								   const std::string &fontStatus)
+void LLVoiceClient::deleteAllVoiceFonts()
 {
+	// All sessions should be removed first as FontIDs will be invalid
+	llassert(mSessions.empty());
+
+	LL_DEBUGS("Voice") << "Clearing voice font list." << LL_ENDL;
+
+	mVoiceFontList.clear();
+
+	voice_font_map_t::iterator iter;
+
+	for (iter = mVoiceFontMap.begin(); iter == mVoiceFontMap.end(); ++iter)
+	{
+		delete iter->second;
+	}
+	mVoiceFontMap.clear();
+}
+
+void LLVoiceClient::addVoiceFont(const S32 font_index,
+								 const std::string &name,
+								 const std::string &description,
+								 const std::string &expiration_date,
+								 const bool has_expired,
+								 const S32 font_type,
+								 const S32 font_status)
+{
+	// Vivox SessionFontIDs are not guaranteed to remain the same between
+	// sessions or grids so use a UUID for the name.
+
+	// If received name is not a UUID, fudge one by hashing the name and type
+	LLUUID font_id;
+	if (LLUUID::validate(name))
+	{
+		font_id = LLUUID(name);
+	}
+	else
+	{
+		font_id.generate(STRINGIZE(font_type << ":" << name));
+	}
+
 	voiceFontEntry *font = NULL;
 
-	voice_font_map_t::iterator iter = mSessionFontMap.find(id);
-	if(iter != mSessionFontMap.end())
+	// Hopefully won't happen, but behave gracefully if there is a duplicate
+	// by Replacing the previous one unless this one has expired.
+	// *TODO: Should maybe check for the later expiry date if neither has
+	// expired, and favour user fonts over root fonts? But as we shouldn't
+	// have duplicates anyway, it's probably not worth the effort.
+	voice_font_map_t::iterator iter = mVoiceFontMap.find(&font_id);
+	bool duplicate = (iter != mVoiceFontMap.end());
+	if (duplicate)
 	{
-		// Found session font already in the map.
-		LL_DEBUGS("Voice") << "existing session font " << id << " : " << name << LL_ENDL;
-		font = iter->second;
+		LL_DEBUGS("Voice") << "Voice font " << font_index << " duplicates " << iter->second->mFontIndex << "!" << LL_ENDL;
+
+		if (!has_expired)
+		{
+			font = iter->second;
+		}
+	}
+	else
+	{
+		font = new voiceFontEntry(font_id);
 	}
 
-	if(font == NULL)
+	if (font)
 	{
-		LL_DEBUGS("Voice") << "adding session font " << id << " : " << name << (hasExpired?" (Expired)":"") << LL_ENDL;
-		font = new voiceFontEntry(id);
-		font->mName = name;
-		font->mDescription = description;
-		font->mExpirationDate = expirationDate;
-		font->mHasExpired = hasExpired;
-		font->mFontType = fontType;
-		font->mFontStatus = fontStatus;
+		font->mFontIndex = font_index;
+		// Use the description for the human readable name if available, as the
+		// "name" will probably be a UUID.
+		font->mName = description.empty() ? name : description;
+		font->mExpirationDate = expiration_date;
+		font->mHasExpired = has_expired;
+		font->mFontType = font_type;
+		font->mFontStatus = font_status;
+
+		LL_DEBUGS("Voice") << "Adding voice font : " << font_id << " (" << font_index << ") : " << name << (has_expired?" (Expired)":"") << LL_ENDL;
+
+		if (font_type < VOICE_FONT_TYPE_NONE || font_type >= VOICE_FONT_TYPE_UNKNOWN)
+		{
+			LL_DEBUGS("Voice") << "Unknown voice font type: " << font_type << LL_ENDL;
+		}
+		if (font_status < VOICE_FONT_STATUS_NONE || font_status >= VOICE_FONT_STATUS_UNKNOWN)
+		{
+			LL_DEBUGS("Voice") << "Unknown voice font status: " << font_status << LL_ENDL;
+		}
 
-		mSessionFontList.insert(voice_font_list_t::value_type(font->mID, &(font->mName)));
-		mSessionFontMap.insert(voice_font_map_t::value_type(font->mID, font));
+		if (!duplicate)
+		{
+			mVoiceFontMap.insert(voice_font_map_t::value_type(&(font->mID), font));
+			mVoiceFontList.insert(voice_font_list_t::value_type(&(font->mName), &(font->mID)));
+		}
 	}
 }
 
-bool LLVoiceClient::setVoiceFont(voice_font_id_t id)
+bool LLVoiceClient::setVoiceFont(const LLUUID& id)
 {
-	if (!mAudioSession || !mAudioSession->mVoiceEnabled || !mSessionFontsReceived)
+	if (!mAudioSession || !mAudioSession->mVoiceEnabled || !hasVoiceFonts())
 	{
-		LL_DEBUGS("Voice") << "Session fonts not available" << LL_ENDL;
+		LL_DEBUGS("Voice") << "Voice fonts not available." << LL_ENDL;
 		return false;
 	}
 
-	if(id == 0 || mSessionFontMap.find(id) != mSessionFontMap.end())
+	if (id.isNull() || (mVoiceFontMap.find(&id) != mVoiceFontMap.end()))
 	{
-		mFontID = id;
+		// *TODO: Check for expired fonts
+		mAudioSession->mVoiceFontID = id;
 	}
 	else
 	{
-		LL_DEBUGS("Voice") << "Invalid session font " << id << LL_ENDL;
+		LL_DEBUGS("Voice") << "Invalid voice font " << id << LL_ENDL;
 		return false;
 	}
 
@@ -7221,9 +7277,48 @@ bool LLVoiceClient::setVoiceFont(voice_font_id_t id)
 	return true;
 }
 
-const LLVoiceClient::voice_font_id_t LLVoiceClient::getVoiceFont() const
+const LLUUID LLVoiceClient::getVoiceFont()
+{
+	if (mAudioSession)
+	{
+		return getVoiceFont(mAudioSession->mHandle);
+	}
+	else
+	{
+		return LLUUID::null;
+	}
+}
+
+const LLUUID LLVoiceClient::getVoiceFont(const std::string &session_handle)
+{
+	LLUUID result;
+	if (hasVoiceFonts())
+	{
+		sessionState *session = findSession(session_handle);
+		if (session)
+		{
+			result = mAudioSession->mVoiceFontID;
+		}
+	}
+	return result;
+}
+
+S32 LLVoiceClient::getVoiceFontIndex(const LLUUID& id) const
 {
-	return mFontID;
+	S32 result = 0;
+	if (!id.isNull())
+	{
+		voice_font_map_t::const_iterator it = mVoiceFontMap.find(&id);
+		if (it != mVoiceFontMap.end())
+		{
+			result = it->second->mFontIndex;
+		}
+		else
+		{
+			LL_DEBUGS("Voice") << "Selected voice font " << id << " is not available." << LL_ENDL;
+		}
+	}
+	return result;
 }
 
 void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
@@ -7240,9 +7335,7 @@ void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std
 
 void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString)
 {
-	// Session font list entries were updated via addSessionFont() during parsing.  Just flag that we're done.
-	mSessionFontsReceived = true;
-
+	// Voice font list entries were updated via addVoiceFont() during parsing.
 	if(getState() == stateLoggedIn)
 	{
 		setState(stateFontListReceived);
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 9409e19644..f6af389b60 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -358,6 +358,8 @@ static	void updatePosition(void);
 			bool		mParticipantsChanged;
 			participantMap mParticipantsByURI;
 			participantUUIDMap mParticipantsByUUID;
+
+			LLUUID		mVoiceFontID;
 		};
 
 		participantState *findParticipantByID(const LLUUID& id);
@@ -431,35 +433,24 @@ static	void updatePosition(void);
 		void accountListBlockRulesResponse(int statusCode, const std::string &statusString);						
 		void accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString);
 
-		struct voiceFontEntry
-		{
-			voiceFontEntry(S32 id);
-			S32			mID;
-			std::string mName;
-			std::string mDescription;
-			std::string mExpirationDate;
-			bool		mHasExpired;
-			std::string mFontType;
-			std::string mFontStatus;
-		};
-
-		typedef S32 voice_font_id_t;
-		typedef std::map<voice_font_id_t, std::string*> voice_font_list_t;
-		typedef std::map<voice_font_id_t, voiceFontEntry*> voice_font_map_t;
-
-		bool getVoiceFontsAvailable() const { return mSessionFontsReceived; };
-		bool setVoiceFont(voice_font_id_t id);
-		const voice_font_id_t getVoiceFont() const;
-		const voice_font_list_t &getVoiceFontList() const { return mSessionFontList; };
-
-		void clearSessionFonts();
-		void addSessionFont(const voice_font_id_t &id,
-							const std::string &name,
-							const std::string &description,
-							const std::string &expirationDate,
-							const bool hasExpired,
-							const std::string &fontType,
-							const std::string &fontStatus);
+		/////////////////////////////
+		// Voice Fonts
+		bool hasVoiceFonts() const { return !mVoiceFontMap.empty(); };
+		bool setVoiceFont(const LLUUID& id);
+		const LLUUID getVoiceFont();
+		const LLUUID getVoiceFont(const std::string &session_handle);
+
+		typedef std::multimap<const std::string*, const LLUUID*, stringMapComparitor> voice_font_list_t;
+
+		const voice_font_list_t &getVoiceFontList() const { return mVoiceFontList; };
+
+		void addVoiceFont(const S32 id,
+						  const std::string &name,
+						  const std::string &description,
+						  const std::string &expiration_date,
+						  const bool has_expired,
+						  const S32 font_type,
+						  const S32 font_status);
 		void accountGetSessionFontsResponse(int statusCode, const std::string &statusString);
 
 		/////////////////////////////
@@ -698,10 +689,46 @@ static	void updatePosition(void);
 		bool mAutoAcceptRulesListReceived;
 		buddyListMap mBuddyListMap;
 
-		bool mSessionFontsReceived;
-		S32 mFontID;
-		voice_font_list_t mSessionFontList;
-		voice_font_map_t mSessionFontMap; // *TODO: make private
+		// Voice Fonts
+
+		S32 getVoiceFontIndex(const LLUUID& id) const;
+		void deleteAllVoiceFonts();
+
+		typedef enum e_voice_font_type
+		{
+			VOICE_FONT_TYPE_NONE = 0,
+			VOICE_FONT_TYPE_ROOT = 1,
+			VOICE_FONT_TYPE_USER = 2,
+			VOICE_FONT_TYPE_UNKNOWN
+		} EVoiceFontType;
+
+		typedef enum e_voice_font_status
+		{
+			VOICE_FONT_STATUS_NONE = 0,
+			VOICE_FONT_STATUS_FREE = 1,
+			VOICE_FONT_STATUS_NOT_FREE = 2,
+			VOICE_FONT_STATUS_UNKNOWN
+		} EVoiceFontStatus;
+
+		struct voiceFontEntry
+		{
+			voiceFontEntry(LLUUID& id);
+			~voiceFontEntry();
+
+			LLUUID		mID;
+			S32			mFontIndex;
+			std::string mName;
+			std::string mExpirationDate;
+			bool		mHasExpired;
+			S32			mFontType;
+			S32			mFontStatus;
+		};
+		typedef std::map<const LLUUID*, voiceFontEntry*, uuidMapComparitor> voice_font_map_t;
+
+		voice_font_map_t	mVoiceFontMap;
+		voice_font_list_t	mVoiceFontList;
+
+		// Audio devices
 
 		deviceList mCaptureDevices;
 		deviceList mRenderDevices;
@@ -714,8 +741,8 @@ static	void updatePosition(void);
 		// This should be called when the code detects we have changed parcels.
 		// It initiates the call to the server that gets the parcel channel.
 		void parcelChanged();
-		
-	void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
+
+		void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
 		void joinSession(sessionState *session);
 		
 static 	std::string nameFromAvatar(LLVOAvatar *avatar);
-- 
cgit v1.2.3


From d6549677fb0a1f1816813db8be6a04ee55e8b8e1 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Mon, 19 Apr 2010 15:38:17 +0100
Subject: Removed left over initialization to 0 of mVoiceFontID from when it
 was an integer rather than a UUID.

---
 indra/newview/llvoiceclient.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 8b88fd46a3..6205617016 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6633,8 +6633,7 @@ LLVoiceClient::sessionState::sessionState() :
 	mReconnect(false),
 	mVolumeDirty(false),
 	mMuteDirty(false),
-	mParticipantsChanged(false),
-	mVoiceFontID(0)
+	mParticipantsChanged(false)
 {
 }
 
-- 
cgit v1.2.3


From 7fc33646853e6853f4afb26079afe1512198c24e Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Tue, 20 Apr 2010 03:23:03 +0100
Subject: Sort out the state machine in LLVoiceClient to wait for voice fonts
 properly.

---
 indra/newview/llvoiceclient.cpp | 34 +++++++++++++++++-----------------
 indra/newview/llvoiceclient.h   |  3 ++-
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 6205617016..b1f0380029 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -1715,7 +1715,8 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
 		CASE(stateNeedsLogin);
 		CASE(stateLoggingIn);
 		CASE(stateLoggedIn);
-		CASE(stateFontListReceived);
+		CASE(stateVoiceFontsWait);
+		CASE(stateVoiceFontsReceived);
 		CASE(stateCreatingSessionGroup);
 		CASE(stateNoChannel);
 		CASE(stateJoiningSession);
@@ -2293,6 +2294,7 @@ void LLVoiceClient::stateMachine()
 			notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
 
 			// request the set of available voice fonts
+			setState(stateVoiceFontsWait);
 			accountGetSessionFontsSendMessage();
 
 			// request the current set of block rules (we'll need them when updating the friends list)
@@ -2326,17 +2328,21 @@ void LLVoiceClient::stateMachine()
 					writeString(stream.str());
 				}
 			}
-
-			// accountGetSessionFontsResponse() will transition from here to stateFontListReceived.
-
-		//MARK: stateFontListReceived
-		case stateFontListReceived:		// font list received
+		break;
 			
+		//MARK: stateVoiceFontsWait
+		case stateVoiceFontsWait:		// Await voice font list
+			// accountGetSessionFontsResponse() will transition from here to
+			// stateVoiceFontsReceived, to ensure we have the voice font list
+			// before attempting to create a session.
+		break;
+
+		//MARK: stateVoiceFontsReceived
+		case stateVoiceFontsReceived:		// Voice font list received
 #if USE_SESSION_GROUPS			
 			// create the main session group
-			sessionGroupCreateSendMessage();
-			
 			setState(stateCreatingSessionGroup);
+			sessionGroupCreateSendMessage();
 #else
 			// Not using session groups -- skip the stateCreatingSessionGroup state.
 			setState(stateNoChannel);
@@ -7162,16 +7168,10 @@ LLVoiceClient::voiceFontEntry::~voiceFontEntry()
 
 void LLVoiceClient::deleteAllVoiceFonts()
 {
-	// All sessions should be removed first as FontIDs will be invalid
-	llassert(mSessions.empty());
-
-	LL_DEBUGS("Voice") << "Clearing voice font list." << LL_ENDL;
-
 	mVoiceFontList.clear();
 
 	voice_font_map_t::iterator iter;
-
-	for (iter = mVoiceFontMap.begin(); iter == mVoiceFontMap.end(); ++iter)
+	for (iter = mVoiceFontMap.begin(); iter != mVoiceFontMap.end(); ++iter)
 	{
 		delete iter->second;
 	}
@@ -7335,9 +7335,9 @@ void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std
 void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::string &statusString)
 {
 	// Voice font list entries were updated via addVoiceFont() during parsing.
-	if(getState() == stateLoggedIn)
+	if(getState() == stateVoiceFontsWait)
 	{
-		setState(stateFontListReceived);
+		setState(stateVoiceFontsReceived);
 	}
 }
 
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index f6af389b60..16fcb1d3f6 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -587,7 +587,8 @@ static	void updatePosition(void);
 			stateNeedsLogin,			// send login request
 			stateLoggingIn,				// waiting for account handle
 			stateLoggedIn,				// account handle received
-			stateFontListReceived,		// List of available voice fonts received
+			stateVoiceFontsWait,		// Awaiting the list of voice fonts
+			stateVoiceFontsReceived,	// List of voice fonts received
 			stateCreatingSessionGroup,	// Creating the main session group
 			stateNoChannel,				// 
 			stateJoiningSession,		// waiting for session handle
-- 
cgit v1.2.3


From cacfa18643092547e7665b36d482ad9c8c5dfc54 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Wed, 28 Apr 2010 03:33:15 +0100
Subject: Persist Voice Font selection.

Added 'VoiceFontDefault' saved setting.
Implemented LLVoiceClientFontsObserver to update the UI when the voice font list is received.
Renamed LLVoiceClientParticipantObserver::onChange() to onParticipantsChanged to avoid ambiguity and make the code more readable.
Made the Voice Font combo in the VCP auto resize to make best use of the available space when the 'Leave Call button is not visible.
---
 indra/newview/app_settings/settings.xml            | 11 ++++
 indra/newview/llcallfloater.cpp                    | 64 ++++++++++------------
 indra/newview/llcallfloater.h                      | 10 +++-
 indra/newview/llparticipantlist.cpp                |  2 +-
 indra/newview/llspeakingindicatormanager.cpp       |  4 +-
 indra/newview/llvoicechannel.h                     |  2 +-
 indra/newview/llvoiceclient.cpp                    | 35 +++++++++++-
 indra/newview/llvoiceclient.h                      | 17 +++++-
 .../default/xui/en/floater_voice_controls.xml      | 12 ++--
 9 files changed, 106 insertions(+), 51 deletions(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4ca23e14a1..63e8775d04 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10405,6 +10405,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>VoiceFontDefault</key>
+    <map>
+      <key>Comment</key>
+      <string>Selected voice font</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>00000000-0000-0000-0000-000000000000</string>
+    </map>
     <key>AutoDisengageMic</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index f41875f67b..703c7dd435 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -115,7 +115,8 @@ LLCallFloater::LLCallFloater(const LLSD& key)
 	mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
 
 	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
-	LLVoiceClient::getInstance()->addObserver(this);
+	LLVoiceClient::instance().addObserver(dynamic_cast<LLVoiceClientParticipantObserver*>(this));
+	LLVoiceClient::instance().addObserver(dynamic_cast<LLVoiceClientFontsObserver*>(this));
 	LLTransientFloaterMgr::getInstance()->addControlView(this);
 
 	// force docked state since this floater doesn't save it between recreations
@@ -135,7 +136,8 @@ LLCallFloater::~LLCallFloater()
 
 	if(LLVoiceClient::instanceExists())
 	{
-		LLVoiceClient::instance().removeObserver(this);
+		LLVoiceClient::instance().removeObserver(dynamic_cast<LLVoiceClientParticipantObserver*>(this));
+		LLVoiceClient::instance().removeObserver(dynamic_cast<LLVoiceClientFontsObserver*>(this));
 	}
 	LLTransientFloaterMgr::getInstance()->removeControlView(this);
 }
@@ -208,11 +210,8 @@ void LLCallFloater::draw()
 }
 
 // virtual
-void LLCallFloater::onChange()
+void LLCallFloater::onParticipantsChanged()
 {
-	// *FIX: Temporarily dumping this here till I decide where it should go
-	updateVoiceFont();
-
 	if (NULL == mParticipants) return;
 
 	updateParticipantsVoiceState();
@@ -226,42 +225,23 @@ void LLCallFloater::onChange()
 	}
 }
 
-//////////////////////////////////////////////////////////////////////////
-/// PRIVATE SECTION
-//////////////////////////////////////////////////////////////////////////
-
-void LLCallFloater::leaveCall()
-{
-	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
-	if (voice_channel)
-	{
-		gIMMgr->endCall(voice_channel->getSessionID());
-	}
-}
-
-/* static */
-void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata)
-{
-	LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue());
-}
-
-void LLCallFloater::updateVoiceFont()
+// virtual
+void LLCallFloater::onVoiceFontsChanged()
 {
 	if (mVoiceFont)
 	{
 		mVoiceFont->removeall();
 		mVoiceFont->add(getString("no_voice_font"), LLUUID::null);
 
-		if (LLVoiceClient::getInstance()->hasVoiceFonts())
+		if (LLVoiceClient::instance().hasVoiceFonts())
 		{
-			const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::getInstance()->getVoiceFontList();
-
+			const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::instance().getVoiceFontList();
 			for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it)
 			{
 				mVoiceFont->add(*(it->first), *(it->second), ADD_BOTTOM);
 			}
 			mVoiceFont->setEnabled(true);
-			mVoiceFont->setValue(LLVoiceClient::getInstance()->getVoiceFont());
+			mVoiceFont->setValue(LLVoiceClient::instance().getVoiceFont());
 		}
 		else
 		{
@@ -270,6 +250,25 @@ void LLCallFloater::updateVoiceFont()
 	}
 }
 
+//////////////////////////////////////////////////////////////////////////
+/// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+
+void LLCallFloater::leaveCall()
+{
+	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+	if (voice_channel)
+	{
+		gIMMgr->endCall(voice_channel->getSessionID());
+	}
+}
+
+/* static */
+void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata)
+{
+	LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue());
+}
+
 void LLCallFloater::updateSession()
 {
 	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
@@ -334,7 +333,7 @@ void LLCallFloater::updateSession()
 	}
 
 	updateTitle();
-	
+
 	//hide "Leave Call" button for nearby chat
 	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
 	childSetVisible("leave_call_btn_panel", !is_local_chat);
@@ -787,9 +786,6 @@ void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
 	{
 		reset(new_state);
 	}
-
-	// *FIX: Dumped here till I decide where to put it
-	updateVoiceFont();
 }
 
 void LLCallFloater::reset(const LLVoiceChannel::EState& new_state)
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 9a13d853c9..160eff312c 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -58,7 +58,9 @@ class LLSpeakersDelayActionsStorage;
  * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel
  * also provides a 'Leave Call' button to allow the Resident to leave that voice channel.
  */
-class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver
+class LLCallFloater : public LLTransientDockableFloater,
+							 LLVoiceClientParticipantObserver,
+							 LLVoiceClientFontsObserver
 {
 public:
 
@@ -76,7 +78,10 @@ public:
 	 *
 	 * Refreshes list to display participants not in voice as disabled.
 	 */
-	/*virtual*/ void onChange();
+	/*virtual*/ void onParticipantsChanged();
+
+	/// Called by LLVoiceClient::notifyVoiceFontObservers when voice font list is changed.
+	/*virtual*/ void onVoiceFontsChanged();
 
 	static void sOnCurrentChannelChanged(const LLUUID& session_id);
 
@@ -103,7 +108,6 @@ private:
 	void leaveCall();
 
 	static void commitVoiceFont(LLUICtrl*,void* userdata);
-	void updateVoiceFont();
 
 	/**
 	 * Updates mSpeakerManager and list according to current Voice Channel
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index c3748ca81d..d0c882e16e 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -92,7 +92,7 @@ public:
 		mAvalineCallers.insert(avaline_caller_id);
 	}
 
-	void onChange()
+	void onParticipantsChanged()
 	{
 		uuid_set_t participant_uuids;
 		LLVoiceClient::getInstance()->getParticipantsUUIDSet(participant_uuids);
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index cc06179481..70028dc21b 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -107,7 +107,7 @@ private:
 	 * So, method does not calculate difference between these list it only switches off already 
 	 * switched on indicators and switches on indicators of voice channel participants
 	 */
-	void onChange();
+	void onParticipantsChanged();
 
 	/**
 	 * Changes state of indicators specified by LLUUIDs
@@ -205,7 +205,7 @@ void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_
 	mSwitchedIndicatorsOn.clear();
 }
 
-void SpeakingIndicatorManager::onChange()
+void SpeakingIndicatorManager::onParticipantsChanged()
 {
 	LL_DEBUGS("SpeakingIndicator") << "Voice participant list was changed, updating indicators" << LL_ENDL;
 
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 941cccacc3..5236b11853 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -112,7 +112,7 @@ protected:
 	void doSetState(const EState& state);
 	void setURI(std::string uri);
 
-	// there can be two directions ICOMING and OUTGOING
+	// there can be two directions INCOMING and OUTGOING
 	EDirection mCallDirection;
 
 	std::string	mURI;
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index b1f0380029..d131285512 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6641,6 +6641,7 @@ LLVoiceClient::sessionState::sessionState() :
 	mMuteDirty(false),
 	mParticipantsChanged(false)
 {
+	mVoiceFontID = LLUUID(gSavedSettings.getString("VoiceFontDefault"));
 }
 
 LLVoiceClient::sessionState::~sessionState()
@@ -7263,8 +7264,11 @@ bool LLVoiceClient::setVoiceFont(const LLUUID& id)
 
 	if (id.isNull() || (mVoiceFontMap.find(&id) != mVoiceFontMap.end()))
 	{
-		// *TODO: Check for expired fonts
+		// *TODO: Check for expired fonts?
 		mAudioSession->mVoiceFontID = id;
+
+		// *TODO: Separate voice font defaults for spatial chat and IM?
+		gSavedSettings.setString("VoiceFontDefault", id.asString());
 	}
 	else
 	{
@@ -7273,6 +7277,7 @@ bool LLVoiceClient::setVoiceFont(const LLUUID& id)
 	}
 
 	sessionSetVoiceFontSendMessage(mAudioSession);
+	notifyVoiceFontObservers();
 	return true;
 }
 
@@ -7339,6 +7344,7 @@ void LLVoiceClient::accountGetSessionFontsResponse(int statusCode, const std::st
 	{
 		setState(stateVoiceFontsReceived);
 	}
+	notifyVoiceFontObservers();
 }
 
 void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
@@ -7358,12 +7364,35 @@ void LLVoiceClient::notifyParticipantObservers()
 		)
 	{
 		LLVoiceClientParticipantObserver* observer = *it;
-		observer->onChange();
-		// In case onChange() deleted an entry.
+		observer->onParticipantsChanged();
+		// In case onParticipantsChanged() deleted an entry.
 		it = mParticipantObservers.upper_bound(observer);
 	}
 }
 
+void LLVoiceClient::addObserver(LLVoiceClientFontsObserver* observer)
+{
+	mVoiceFontObservers.insert(observer);
+}
+
+void LLVoiceClient::removeObserver(LLVoiceClientFontsObserver* observer)
+{
+	mVoiceFontObservers.erase(observer);
+}
+
+void LLVoiceClient::notifyVoiceFontObservers()
+{
+	for (voice_font_observer_set_t::iterator it = mVoiceFontObservers.begin();
+		 it != mVoiceFontObservers.end();
+		 )
+	{
+		LLVoiceClientFontsObserver* observer = *it;
+		observer->onVoiceFontsChanged();
+		// In case onVoiceFontsChanged() deleted an entry.
+		it = mVoiceFontObservers.upper_bound(observer);
+	}
+}
+
 void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
 {
 	mStatusObservers.insert(observer);
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 16fcb1d3f6..a1083652aa 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -49,7 +49,14 @@ class LLVoiceClientParticipantObserver
 {
 public:
 	virtual ~LLVoiceClientParticipantObserver() { }
-	virtual void onChange() = 0;
+	virtual void onParticipantsChanged() = 0;
+};
+
+class LLVoiceClientFontsObserver
+{
+public:
+	virtual ~LLVoiceClientFontsObserver() { }
+	virtual void onVoiceFontsChanged() = 0;
 };
 
 class LLVoiceClientStatusObserver
@@ -500,6 +507,9 @@ static	void updatePosition(void);
 		void addObserver(LLVoiceClientParticipantObserver* observer);
 		void removeObserver(LLVoiceClientParticipantObserver* observer);
 
+		void addObserver(LLVoiceClientFontsObserver* observer);
+		void removeObserver(LLVoiceClientFontsObserver* observer);
+
 		void addObserver(LLVoiceClientStatusObserver* observer);
 		void removeObserver(LLVoiceClientStatusObserver* observer);
 
@@ -832,6 +842,11 @@ static	std::string nameFromsipURI(const std::string &uri);
 
 		void notifyParticipantObservers();
 
+		typedef std::set<LLVoiceClientFontsObserver*> voice_font_observer_set_t;
+		voice_font_observer_set_t mVoiceFontObservers;
+
+		void notifyVoiceFontObservers();
+
 		typedef std::set<LLVoiceClientStatusObserver*> status_observer_set_t;
 		status_observer_set_t mStatusObservers;
 		
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index e7c5770a08..885c8304eb 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -101,20 +101,20 @@
          orientation="horizontal"
          width="263">
           <layout_panel
-           auto_resize="false"
+           auto_resize="true"
            user_resize="false"
            follows="top|left"
            height="26"
            visible="true"
            layout="topleft"
            name="voice_font_panel"
-           width="120">
+           width="150">
             <combo_box
-             follows="left|top"
+             follows="left|top|right"
              height="23"
              name="voice_font"
              top_pad="0"
-             width="120">
+             width="150">
               <combo_box.item
                 label="No Voice Effect"
                 name="no_voice_font"
@@ -124,14 +124,14 @@
         <layout_panel
           auto_resize="false"
           user_resize="false" 
-          follows="top|left"
+          follows="top|right"
           height="26"
           visible="true"
           layout="topleft"
           name="leave_call_btn_panel"
           width="100">
            <button
-          follows="right|top"
+            follows="right|top"
             height="23"
             top_pad="0"
             label="Leave Call"
-- 
cgit v1.2.3


From 46897efc3efade25feaaa1dc67bc131c35202d12 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Thu, 29 Apr 2010 02:37:07 +0100
Subject: Make a proper XUI commit_callback for the Voice Font combo

---
 indra/newview/llcallfloater.cpp                    | 50 +++++++++++++---------
 indra/newview/llcallfloater.h                      |  3 +-
 indra/newview/llvoiceclient.cpp                    | 49 +++++++++------------
 indra/newview/llvoiceclient.h                      |  1 +
 .../default/xui/en/floater_voice_controls.xml      |  9 ++--
 5 files changed, 58 insertions(+), 54 deletions(-)

diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 703c7dd435..37e551890a 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -115,8 +115,10 @@ LLCallFloater::LLCallFloater(const LLSD& key)
 	mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
 
 	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
+
 	LLVoiceClient::instance().addObserver(dynamic_cast<LLVoiceClientParticipantObserver*>(this));
 	LLVoiceClient::instance().addObserver(dynamic_cast<LLVoiceClientFontsObserver*>(this));
+	mCommitCallbackRegistrar.add("Voice.CommitVoiceFont", boost::bind(&LLCallFloater::onCommitVoiceFont, this));
 	LLTransientFloaterMgr::getInstance()->addControlView(this);
 
 	// force docked state since this floater doesn't save it between recreations
@@ -152,8 +154,6 @@ BOOL LLCallFloater::postBuild()
 	childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
 
 	mVoiceFont = getChild<LLComboBox>("voice_font");
-	childSetCommitCallback("voice_font", commitVoiceFont, this); // *FIX: childSetCommitCallback deprecated
-
 	mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
 	mNonAvatarCaller->setVisible(FALSE);
 
@@ -227,6 +227,32 @@ void LLCallFloater::onParticipantsChanged()
 
 // virtual
 void LLCallFloater::onVoiceFontsChanged()
+{
+	updateVoiceFont();
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// PRIVATE SECTION
+//////////////////////////////////////////////////////////////////////////
+
+void LLCallFloater::leaveCall()
+{
+	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+	if (voice_channel)
+	{
+		gIMMgr->endCall(voice_channel->getSessionID());
+	}
+}
+
+void LLCallFloater::onCommitVoiceFont()
+{
+	if (LLVoiceClient::instance().hasVoiceFonts())
+	{
+		LLVoiceClient::getInstance()->setVoiceFont(mVoiceFont->getValue());
+	}
+}
+
+void LLCallFloater::updateVoiceFont()
 {
 	if (mVoiceFont)
 	{
@@ -250,25 +276,6 @@ void LLCallFloater::onVoiceFontsChanged()
 	}
 }
 
-//////////////////////////////////////////////////////////////////////////
-/// PRIVATE SECTION
-//////////////////////////////////////////////////////////////////////////
-
-void LLCallFloater::leaveCall()
-{
-	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
-	if (voice_channel)
-	{
-		gIMMgr->endCall(voice_channel->getSessionID());
-	}
-}
-
-/* static */
-void LLCallFloater::commitVoiceFont(LLUICtrl* ctrl, void* userdata)
-{
-	LLVoiceClient::getInstance()->setVoiceFont(ctrl->getValue());
-}
-
 void LLCallFloater::updateSession()
 {
 	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
@@ -333,6 +340,7 @@ void LLCallFloater::updateSession()
 	}
 
 	updateTitle();
+	updateVoiceFont();
 
 	//hide "Leave Call" button for nearby chat
 	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 160eff312c..90b23eb4c4 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -107,7 +107,8 @@ private:
 
 	void leaveCall();
 
-	static void commitVoiceFont(LLUICtrl*,void* userdata);
+	void onCommitVoiceFont();
+	void updateVoiceFont();
 
 	/**
 	 * Updates mSpeakerManager and list according to current Voice Channel
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index d131285512..657a130c27 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -7256,55 +7256,46 @@ void LLVoiceClient::addVoiceFont(const S32 font_index,
 
 bool LLVoiceClient::setVoiceFont(const LLUUID& id)
 {
-	if (!mAudioSession || !mAudioSession->mVoiceEnabled || !hasVoiceFonts())
+	return mAudioSession ? setVoiceFont(mAudioSession->mHandle, id) : false;
+}
+
+bool LLVoiceClient::setVoiceFont(const std::string &session_handle, const LLUUID& id)
+{
+	sessionState *session = findSession(session_handle);
+
+	if (!session || !session->mVoiceEnabled || !hasVoiceFonts())
 	{
 		LL_DEBUGS("Voice") << "Voice fonts not available." << LL_ENDL;
 		return false;
 	}
 
-	if (id.isNull() || (mVoiceFontMap.find(&id) != mVoiceFontMap.end()))
-	{
-		// *TODO: Check for expired fonts?
-		mAudioSession->mVoiceFontID = id;
-
-		// *TODO: Separate voice font defaults for spatial chat and IM?
-		gSavedSettings.setString("VoiceFontDefault", id.asString());
-	}
-	else
+	if (!id.isNull() && (mVoiceFontMap.find(&id) == mVoiceFontMap.end()))
 	{
 		LL_DEBUGS("Voice") << "Invalid voice font " << id << LL_ENDL;
 		return false;
 	}
 
-	sessionSetVoiceFontSendMessage(mAudioSession);
+	// *TODO: Check for expired fonts?
+	mAudioSession->mVoiceFontID = id;
+
+	// *TODO: Separate voice font defaults for spatial chat and IM?
+	gSavedSettings.setString("VoiceFontDefault", id.asString());
+
+	sessionSetVoiceFontSendMessage(session);
 	notifyVoiceFontObservers();
+
 	return true;
 }
 
 const LLUUID LLVoiceClient::getVoiceFont()
 {
-	if (mAudioSession)
-	{
-		return getVoiceFont(mAudioSession->mHandle);
-	}
-	else
-	{
-		return LLUUID::null;
-	}
+	return mAudioSession ? getVoiceFont(mAudioSession->mHandle) : LLUUID::null;
 }
 
 const LLUUID LLVoiceClient::getVoiceFont(const std::string &session_handle)
 {
-	LLUUID result;
-	if (hasVoiceFonts())
-	{
-		sessionState *session = findSession(session_handle);
-		if (session)
-		{
-			result = mAudioSession->mVoiceFontID;
-		}
-	}
-	return result;
+	sessionState *session = findSession(session_handle);
+	return session ? session->mVoiceFontID : LLUUID::null;
 }
 
 S32 LLVoiceClient::getVoiceFontIndex(const LLUUID& id) const
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index a1083652aa..a997f9d500 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -444,6 +444,7 @@ static	void updatePosition(void);
 		// Voice Fonts
 		bool hasVoiceFonts() const { return !mVoiceFontMap.empty(); };
 		bool setVoiceFont(const LLUUID& id);
+		bool setVoiceFont(const std::string &session_handle, const LLUUID& id);
 		const LLUUID getVoiceFont();
 		const LLUUID getVoiceFont(const std::string &session_handle);
 
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index 885c8304eb..44840a82d0 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -110,15 +110,18 @@
            name="voice_font_panel"
            width="150">
             <combo_box
+             enabled="false"
              follows="left|top|right"
              height="23"
              name="voice_font"
              top_pad="0"
              width="150">
               <combo_box.item
-                label="No Voice Effect"
-                name="no_voice_font"
-                value="0" />
+               label="No Voice Effect"
+               name="no_voice_font"
+               value="0" />
+              <combo_box.commit_callback
+               function="Voice.CommitVoiceFont" />
             </combo_box>
           </layout_panel>
         <layout_panel
-- 
cgit v1.2.3


From 93a93dfc92d5339a70f6174ae74b96fc4cb2813f Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Thu, 29 Apr 2010 13:42:34 +0100
Subject: Added VoiceFontUI setting for SLE

---
 indra/newview/app_settings/settings.xml                       | 11 +++++++++++
 indra/newview/skins/default/xui/en/floater_voice_controls.xml |  2 +-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 45de05ae82..3a80579c7f 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10427,6 +10427,17 @@
       <key>Value</key>
       <string>00000000-0000-0000-0000-000000000000</string>
     </map>
+    <key>VoiceFontUI</key>
+    <map>
+      <key>Comment</key>
+      <string>Whether or not to show the Voice Fonts UI</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>AutoDisengageMic</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index 44840a82d0..ce81a39fe0 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -105,7 +105,7 @@
            user_resize="false"
            follows="top|left"
            height="26"
-           visible="true"
+           visiblity_control="VoiceFontUI"
            layout="topleft"
            name="voice_font_panel"
            width="150">
-- 
cgit v1.2.3


From 29c2e7ebeca288b051d4851d148b1f82a06d24ef Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Thu, 29 Apr 2010 13:47:50 +0100
Subject: Clip the layout_stack so that the "Leave Call" button isn't seen
 flying in and out of the floater!

---
 indra/newview/skins/default/xui/en/floater_voice_controls.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index ce81a39fe0..370bc05c28 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -90,9 +90,9 @@
              width="20" />
         </layout_panel>
         <layout_stack
-         clip="false"
+         clip="true"
          auto_resize="false"
-         follows="left|right"
+         follows="left|top|right"
          height="23"
          layout="topleft"
          left="10"
-- 
cgit v1.2.3


From 38f45a359544ff855c624473fe1305ec6933b8c5 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Thu, 29 Apr 2010 18:38:08 +0100
Subject: Make the current voice font a per-account saved setting.

---
 indra/newview/app_settings/settings.xml             | 11 -----------
 indra/newview/app_settings/settings_per_account.xml | 11 +++++++++++
 indra/newview/llvoiceclient.cpp                     |  4 ++--
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 3a80579c7f..1cb4b15147 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10416,17 +10416,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>VoiceFontDefault</key>
-    <map>
-      <key>Comment</key>
-      <string>Selected voice font</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>00000000-0000-0000-0000-000000000000</string>
-    </map>
     <key>VoiceFontUI</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 3ce32a05b0..1855bb0c0c 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -99,6 +99,17 @@
         <key>Value</key>
             <integer>1</integer>
         </map>
+    <key>VoiceFontDefault</key>
+    <map>
+        <key>Comment</key>
+            <string>Selected voice font</string>
+        <key>Persist</key>
+            <integer>1</integer>
+        <key>Type</key>
+            <string>String</string>
+        <key>Value</key>
+            <string>00000000-0000-0000-0000-000000000000</string>
+    </map>
 
     <!-- Settings below are for back compatibility only.
     They are not used in current viewer anymore. But they can't be removed to avoid
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 657a130c27..497f1db44d 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6641,7 +6641,7 @@ LLVoiceClient::sessionState::sessionState() :
 	mMuteDirty(false),
 	mParticipantsChanged(false)
 {
-	mVoiceFontID = LLUUID(gSavedSettings.getString("VoiceFontDefault"));
+	mVoiceFontID = LLUUID(gSavedPerAccountSettings.getString("VoiceFontDefault"));
 }
 
 LLVoiceClient::sessionState::~sessionState()
@@ -7279,7 +7279,7 @@ bool LLVoiceClient::setVoiceFont(const std::string &session_handle, const LLUUID
 	mAudioSession->mVoiceFontID = id;
 
 	// *TODO: Separate voice font defaults for spatial chat and IM?
-	gSavedSettings.setString("VoiceFontDefault", id.asString());
+	gSavedPerAccountSettings.setString("VoiceFontDefault", id.asString());
 
 	sessionSetVoiceFontSendMessage(session);
 	notifyVoiceFontObservers();
-- 
cgit v1.2.3


From 7a6474129c6015e102b30570fa474ba48e4c85e0 Mon Sep 17 00:00:00 2001
From: Aimee Linden <aimee@lindenlab.com>
Date: Fri, 30 Apr 2010 19:38:52 +0100
Subject: Move the Voice Font control from LLCallFloater to its own panel so
 that it can be reused.

---
 indra/newview/CMakeLists.txt                       |  2 +
 indra/newview/llcallfloater.cpp                    | 57 ++-----------------
 indra/newview/llcallfloater.h                      | 12 +---
 indra/newview/llvoiceclient.cpp                    |  7 ++-
 .../default/xui/en/floater_voice_controls.xml      | 66 +++++++---------------
 5 files changed, 36 insertions(+), 108 deletions(-)

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 835a9aacd5..688886de3a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -350,6 +350,7 @@ set(viewer_SOURCE_FILES
     llpanelprofileview.cpp
     llpanelteleporthistory.cpp
     llpaneltiptoast.cpp
+    llpanelvoicefont.cpp
     llpanelvolume.cpp
     llpanelvolumepulldown.cpp
     llparcelselection.cpp
@@ -857,6 +858,7 @@ set(viewer_HEADER_FILES
     llpanelprofileview.h
     llpanelteleporthistory.h
     llpaneltiptoast.h
+    llpanelvoicefont.h
     llpanelvolume.h
     llpanelvolumepulldown.h
     llparcelselection.h
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 37e551890a..1c03fbde41 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -52,7 +52,7 @@
 #include "lltransientfloatermgr.h"
 #include "llviewerwindow.h"
 #include "llvoicechannel.h"
-#include "llvoiceclient.h" // for Voice font list types
+#include "llviewercontrol.h"
 #include "llviewerparcelmgr.h"
 
 static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids);
@@ -106,7 +106,6 @@ LLCallFloater::LLCallFloater(const LLSD& key)
 , mNonAvatarCaller(NULL)
 , mVoiceType(VC_LOCAL_CHAT)
 , mAgentPanel(NULL)
-, mVoiceFont(NULL)
 , mSpeakingIndicator(NULL)
 , mIsModeratorMutedVoice(false)
 , mInitParticipantsVoiceState(false)
@@ -115,10 +114,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
 	mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
 
 	mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
-
-	LLVoiceClient::instance().addObserver(dynamic_cast<LLVoiceClientParticipantObserver*>(this));
-	LLVoiceClient::instance().addObserver(dynamic_cast<LLVoiceClientFontsObserver*>(this));
-	mCommitCallbackRegistrar.add("Voice.CommitVoiceFont", boost::bind(&LLCallFloater::onCommitVoiceFont, this));
+	LLVoiceClient::instance().addObserver(this);
 	LLTransientFloaterMgr::getInstance()->addControlView(this);
 
 	// force docked state since this floater doesn't save it between recreations
@@ -138,8 +134,7 @@ LLCallFloater::~LLCallFloater()
 
 	if(LLVoiceClient::instanceExists())
 	{
-		LLVoiceClient::instance().removeObserver(dynamic_cast<LLVoiceClientParticipantObserver*>(this));
-		LLVoiceClient::instance().removeObserver(dynamic_cast<LLVoiceClientFontsObserver*>(this));
+		LLVoiceClient::instance().removeObserver(this);
 	}
 	LLTransientFloaterMgr::getInstance()->removeControlView(this);
 }
@@ -153,7 +148,6 @@ BOOL LLCallFloater::postBuild()
 
 	childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
 
-	mVoiceFont = getChild<LLComboBox>("voice_font");
 	mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
 	mNonAvatarCaller->setVisible(FALSE);
 
@@ -225,12 +219,6 @@ void LLCallFloater::onParticipantsChanged()
 	}
 }
 
-// virtual
-void LLCallFloater::onVoiceFontsChanged()
-{
-	updateVoiceFont();
-}
-
 //////////////////////////////////////////////////////////////////////////
 /// PRIVATE SECTION
 //////////////////////////////////////////////////////////////////////////
@@ -244,38 +232,6 @@ void LLCallFloater::leaveCall()
 	}
 }
 
-void LLCallFloater::onCommitVoiceFont()
-{
-	if (LLVoiceClient::instance().hasVoiceFonts())
-	{
-		LLVoiceClient::getInstance()->setVoiceFont(mVoiceFont->getValue());
-	}
-}
-
-void LLCallFloater::updateVoiceFont()
-{
-	if (mVoiceFont)
-	{
-		mVoiceFont->removeall();
-		mVoiceFont->add(getString("no_voice_font"), LLUUID::null);
-
-		if (LLVoiceClient::instance().hasVoiceFonts())
-		{
-			const LLVoiceClient::voice_font_list_t font_list = LLVoiceClient::instance().getVoiceFontList();
-			for (LLVoiceClient::voice_font_list_t::const_iterator it = font_list.begin(); it != font_list.end(); ++it)
-			{
-				mVoiceFont->add(*(it->first), *(it->second), ADD_BOTTOM);
-			}
-			mVoiceFont->setEnabled(true);
-			mVoiceFont->setValue(LLVoiceClient::instance().getVoiceFont());
-		}
-		else
-		{
-			mVoiceFont->setEnabled(false);
-		}
-	}
-}
-
 void LLCallFloater::updateSession()
 {
 	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
@@ -333,23 +289,22 @@ void LLCallFloater::updateSession()
 
 	if (NULL == mSpeakerManager)
 	{
-		// by default let show nearby chat participants
+		// By default show nearby chat participants
 		mSpeakerManager = LLLocalSpeakerMgr::getInstance();
 		lldebugs << "Set DEFAULT speaker manager" << llendl;
 		mVoiceType = VC_LOCAL_CHAT;
 	}
 
 	updateTitle();
-	updateVoiceFont();
 
-	//hide "Leave Call" button for nearby chat
+	// Hide "Leave Call" button for nearby chat
 	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
 	childSetVisible("leave_call_btn_panel", !is_local_chat);
 
 	refreshParticipantList();
 	updateAgentModeratorState();
 
-	//show floater for voice calls & only in CONNECTED to voice channel state
+	// Show floater for voice calls & only in CONNECTED to voice channel state
 	if (!is_local_chat &&
 	    voice_channel &&
 	    LLVoiceChannel::STATE_CONNECTED == voice_channel->getState())
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 90b23eb4c4..e4341175e2 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -40,7 +40,6 @@
 
 class LLAvatarList;
 class LLAvatarListItem;
-class LLComboBox;
 class LLNonAvatarCaller;
 class LLOutputMonitorCtrl;
 class LLParticipantList;
@@ -58,9 +57,7 @@ class LLSpeakersDelayActionsStorage;
  * When the Resident is engaged in any chat except Nearby Chat, the Voice Control Panel
  * also provides a 'Leave Call' button to allow the Resident to leave that voice channel.
  */
-class LLCallFloater : public LLTransientDockableFloater,
-							 LLVoiceClientParticipantObserver,
-							 LLVoiceClientFontsObserver
+class LLCallFloater : public LLTransientDockableFloater, LLVoiceClientParticipantObserver
 {
 public:
 
@@ -80,9 +77,6 @@ public:
 	 */
 	/*virtual*/ void onParticipantsChanged();
 
-	/// Called by LLVoiceClient::notifyVoiceFontObservers when voice font list is changed.
-	/*virtual*/ void onVoiceFontsChanged();
-
 	static void sOnCurrentChannelChanged(const LLUUID& session_id);
 
 private:
@@ -107,9 +101,6 @@ private:
 
 	void leaveCall();
 
-	void onCommitVoiceFont();
-	void updateVoiceFont();
-
 	/**
 	 * Updates mSpeakerManager and list according to current Voice Channel
 	 *
@@ -239,7 +230,6 @@ private:
 	LLNonAvatarCaller* mNonAvatarCaller;
 	EVoiceControls mVoiceType;
 	LLPanel* mAgentPanel;
-	LLComboBox* mVoiceFont;
 	LLOutputMonitorCtrl* mSpeakingIndicator;
 	bool mIsModeratorMutedVoice;
 
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 497f1db44d..007d95043d 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -7262,8 +7262,13 @@ bool LLVoiceClient::setVoiceFont(const LLUUID& id)
 bool LLVoiceClient::setVoiceFont(const std::string &session_handle, const LLUUID& id)
 {
 	sessionState *session = findSession(session_handle);
+	if (!session)
+	{
+		LL_DEBUGS("Voice") << "Invalid Session." << LL_ENDL;
+		return false;
+	}
 
-	if (!session || !session->mVoiceEnabled || !hasVoiceFonts())
+	if (!hasVoiceFonts())
 	{
 		LL_DEBUGS("Voice") << "Voice fonts not available." << LL_ENDL;
 		return false;
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index 370bc05c28..83380577ca 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -3,7 +3,7 @@
  can_resize="true"
  can_minimize="true"
  can_close="false"
- height="202"
+ height="205"
  layout="topleft"
  min_height="124"
  min_width="190"
@@ -35,9 +35,6 @@
      name="no_one_near">
         No one near has voice enabled
     </string>
-    <floater.string name="no_voice_font">
-        No Voice Effect
-    </floater.string>
       <layout_stack
          clip="false"
          follows="all"
@@ -53,7 +50,7 @@
           user_resize="false" 
          auto_resize="false" 
          layout="topleft"
-         height="26"
+         height="20"
          name="my_panel">
             <avatar_icon
              enabled="false"
@@ -93,55 +90,34 @@
          clip="true"
          auto_resize="false"
          follows="left|top|right"
-         height="23"
+         height="26"
          layout="topleft"
-         left="10"
          mouse_opaque="false"
          name="voice_font_and_leave_call_stack"
          orientation="horizontal"
-         width="263">
+         width="262">
+          <panel
+           class="panel_voice_font"
+           name="panel_voice_font"
+           visiblity_control="VoiceFontUI"
+           filename="panel_voice_font.xml" />
           <layout_panel
-           auto_resize="true"
+           auto_resize="false"
            user_resize="false"
-           follows="top|left"
-           height="26"
-           visiblity_control="VoiceFontUI"
+           follows="top|right"
+           height="23"
+           visible="true"
            layout="topleft"
-           name="voice_font_panel"
-           width="150">
-            <combo_box
-             enabled="false"
-             follows="left|top|right"
+           name="leave_call_btn_panel"
+           width="100">
+            <button
+             follows="right|top"
              height="23"
-             name="voice_font"
-             top_pad="0"
-             width="150">
-              <combo_box.item
-               label="No Voice Effect"
-               name="no_voice_font"
-               value="0" />
-              <combo_box.commit_callback
-               function="Voice.CommitVoiceFont" />
-            </combo_box>
+             label="Leave Call"
+             name="leave_call_btn"
+             width="100" />
           </layout_panel>
-        <layout_panel
-          auto_resize="false"
-          user_resize="false" 
-          follows="top|right"
-          height="26"
-          visible="true"
-          layout="topleft"
-          name="leave_call_btn_panel"
-          width="100">
-           <button
-            follows="right|top"
-            height="23"
-            top_pad="0"
-            label="Leave Call"
-            name="leave_call_btn"
-            width="100" />
-         </layout_panel>
-      </layout_stack>
+        </layout_stack>
       <layout_panel
           follows="all"
           layout="topleft"
-- 
cgit v1.2.3