From a556c2e84fc121dacdbb00629c68371b72c5cb7a Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Mon, 29 Jun 2009 17:25:47 -0500
Subject: Updated URL for Mac OpenAL libs package.
---
linden/install.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/linden/install.xml b/linden/install.xml
index 224cd65..b213b94 100644
--- a/linden/install.xml
+++ b/linden/install.xml
@@ -1128,7 +1128,7 @@ anguage Infrstructure (CLI) international standard
md5sum
f30b851e089108978c8218295a405159
url
- http://thomas.shikami.mooo.com/install_pkgs/openal-darwin-20090418.tar.bz2
+ http://imprudenceviewer.org/download/libs/openal-darwin-20090418.tar.bz2
linux
+ DefaultGrid
+
+ Comment
+ Nickname of the default grid
+ Persist
+ 1
+ Type
+ String
+ Value
+ secondlife
+
+ KeepAppearance
+
+ Comment
+ Keep appearance across grid teleport
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 0
+
+ CheckForGridUpdates
+
+ Comment
+ Check for grid info updates on the web server
+ Persist
+ 1
+ Type
+ Boolean
+ Value
+ 1
+
diff --git a/linden/indra/newview/authentication_controller.cpp b/linden/indra/newview/authentication_controller.cpp
new file mode 100644
index 0000000..a060409
--- /dev/null
+++ b/linden/indra/newview/authentication_controller.cpp
@@ -0,0 +1,80 @@
+/*
+ * AuthenticationController.cpp
+ * SecondLife
+ *
+ * Created by RMS on 7/1/08.
+ *
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "authentication_floater.h"
+#include "llviewerobject.h"
+#include "llcheckboxctrl.h"
+#include "llselectmgr.h"
+#include "authentication_controller.h"
+
+// Statics
+std::string AuthenticationController::target_grid;
+std::string AuthenticationController::username;
+std::string AuthenticationController::password;
+BOOL AuthenticationController::store_pw = FALSE;
+
+AuthenticationController::AuthenticationController(const std::string& tg, void (*cb)(void*))
+{
+ target_grid = tg;
+ callback = cb;
+}
+
+AuthenticationController::~AuthenticationController()
+{
+}
+
+// user interface callbacks: all static
+void AuthenticationController::onCommitUser(LLUICtrl* ctrl, void* userdata)
+{
+ AuthenticationFloater *floater = (AuthenticationFloater*)userdata;
+ username = floater->childGetText("User_edit");
+}
+
+void AuthenticationController::onCommitPassword(LLUICtrl* ctrl, void* userdata)
+{
+ AuthenticationFloater *floater = (AuthenticationFloater*)userdata;
+ password = floater->childGetText("Password_edit");
+}
+
+void AuthenticationController::onCommitRemember(LLUICtrl* ctrl, void* userdata)
+{
+ LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
+ if(!object) return;
+
+ LLCheckBoxCtrl *check = (LLCheckBoxCtrl*)ctrl;
+ store_pw = check->get();
+}
+
+void AuthenticationController::onAccept(void* userdata)
+{
+
+}
+
+void AuthenticationController::onCancel(void* userdata)
+{
+ AuthenticationFloater *floater = (AuthenticationFloater*)userdata;
+ floater->cancel();
+ floater->close();
+}
+
+void AuthenticationController::onClickRegister(void* userdata)
+{
+ llinfos << "onClickRegister" << llendl;
+}
+
+void AuthenticationController::retrieveStoredAccountData(void* userdata)
+{
+
+}
+
+// static
+std::string AuthenticationController::getTargetGrid()
+{
+ return target_grid;
+}
diff --git a/linden/indra/newview/authentication_controller.h b/linden/indra/newview/authentication_controller.h
new file mode 100644
index 0000000..db875ea
--- /dev/null
+++ b/linden/indra/newview/authentication_controller.h
@@ -0,0 +1,42 @@
+/*
+ * AuthenticationController.h
+ * SecondLife
+ *
+ * Created by RMS on 7/1/08.
+ *
+ */
+
+#ifndef PL_AuthenticationController_H
+#define PL_AuthenticationController_H
+
+#include "llfloater.h"
+
+class AuthenticationController
+{
+public:
+ AuthenticationController(const std::string& tg, void (*cb)(void*));
+ virtual ~AuthenticationController();
+
+ // line editor callbacks
+ static void onCommitUser(LLUICtrl* ctrl, void* userdata);
+ static void onCommitPassword(LLUICtrl* ctrl, void* userdata);
+ static void onCommitRemember(LLUICtrl* ctrl, void* userdata);
+ // button callbacks
+ static void onAccept(void* userdata);
+ static void onCancel(void* userdata);
+ static void onClickRegister(void* userdata);
+
+ void retrieveStoredAccountData(void* userdata);
+ static std::string getTargetGrid();
+
+private:
+ static std::string target_grid;
+ static std::string username;
+ static std::string password;
+ static BOOL store_pw;
+ void (*callback)(void*);
+};
+
+
+#endif // PL_AuthenticationController_H
+
diff --git a/linden/indra/newview/authentication_floater.cpp b/linden/indra/newview/authentication_floater.cpp
new file mode 100644
index 0000000..2fc7add
--- /dev/null
+++ b/linden/indra/newview/authentication_floater.cpp
@@ -0,0 +1,75 @@
+/*
+ * AuthenticationFloater.cpp
+ * Cross-grid authentication system view.
+ *
+ * Created by RMS on 7/1/08.
+ *
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+#include "authentication_floater.h"
+#include "lluictrlfactory.h"
+
+// Statics
+AuthenticationFloater* AuthenticationFloater::sInstance = NULL;
+AuthenticationController* AuthenticationFloater::sController = NULL;
+
+AuthenticationFloater::AuthenticationFloater()
+: LLFloater("floater_authentication")
+{
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_authentication.xml");
+
+ childSetTextArg("Intro_text", "[TARGET_GRID]", sController->getTargetGrid());
+
+ childSetCommitCallback("User_edit", controller()->onCommitUser, this);
+ childSetCommitCallback("Password_edit", controller()->onCommitPassword, this);
+ childSetCommitCallback("Remember_check", controller()->onCommitRemember, this);
+
+ childSetAction("OK", controller()->onAccept, this);
+ childSetAction("Cancel", controller()->onCancel, this);
+ childSetAction("Register", controller()->onClickRegister, this);
+
+ setDefaultBtn("OK");
+}
+
+AuthenticationFloater::~AuthenticationFloater()
+{
+ sInstance = NULL;
+ delete sController;
+ sController = NULL;
+}
+
+// static
+void AuthenticationFloater::show(void* userdata)
+{
+ std::string target_grid;
+ void (*cb)(void*) = NULL;
+
+ if (!userdata)
+ {
+ target_grid = "Authentication Test";
+ }
+
+ if (!sInstance)
+ sInstance = new AuthenticationFloater();
+ if (!sController)
+ sController = new AuthenticationController(target_grid, cb);
+
+ sInstance->open();
+}
+
+void AuthenticationFloater::accept()
+{
+ llinfos << "accept" << llendl;
+}
+
+void AuthenticationFloater::cancel()
+{
+ llinfos << "cancel" << llendl;
+}
+
+AuthenticationController* AuthenticationFloater::controller()
+{
+ return sController;
+}
diff --git a/linden/indra/newview/authentication_floater.h b/linden/indra/newview/authentication_floater.h
new file mode 100644
index 0000000..b24426b
--- /dev/null
+++ b/linden/indra/newview/authentication_floater.h
@@ -0,0 +1,35 @@
+/*
+ * AuthenticationFloater.h
+ * Cross-grid authentication system view.
+ *
+ * Created by RMS on 7/1/08.
+ *
+ */
+
+#ifndef PL_AuthenticationFloater_H
+#define PL_AuthenticationFloater_H
+
+#include "llfloater.h"
+#include "authentication_controller.h"
+
+class AuthenticationFloater : public LLFloater
+{
+public:
+ AuthenticationFloater();
+ virtual ~AuthenticationFloater();
+
+ static void show(void* userdata);
+ static void accept();
+ static void cancel();
+
+ // data accessors
+ static AuthenticationController* controller();
+
+private:
+ // static because we only need one floater
+ static AuthenticationFloater* sInstance;
+ static AuthenticationController* sController;
+};
+
+
+#endif // PL_AuthenticationFloater_H
diff --git a/linden/indra/newview/authentication_model.cpp b/linden/indra/newview/authentication_model.cpp
new file mode 100644
index 0000000..763ab4a
--- /dev/null
+++ b/linden/indra/newview/authentication_model.cpp
@@ -0,0 +1,111 @@
+/*
+ * authentication_model.cpp
+ * SecondLife
+ *
+ * Created by RMS on 7/17/08.
+ *
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldir.h"
+#include "llfile.h"
+#include "llsdserialize.h"
+#include "authentication_model.h"
+
+AuthenticationModel::AuthenticationModel()
+{
+ loadPersistentData();
+}
+
+AuthenticationModel::~AuthenticationModel()
+{
+ savePersistentData();
+}
+
+void AuthenticationModel::loadPersistentData()
+{
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+ "cross_grid_authentication.xml");
+ LLSD auth_llsd;
+ llifstream file;
+ file.open(filename);
+ if(file.is_open())
+ LLSDSerialize::fromXML(mAuthLLSD, file);
+}
+
+void AuthenticationModel::savePersistentData()
+{
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
+ "cross_grid_authentication.xml");
+ llofstream ofile;
+ ofile.open(filename);
+ LLSDSerialize::toPrettyXML(mAuthLLSD, ofile);
+}
+
+void AuthenticationModel::revert()
+{
+ loadPersistentData();
+}
+
+AuthenticationModel::connection_t AuthenticationModel::subscribeToModelUpdates
+ (event_t::slot_function_type subscriber)
+{
+ return mEventUpdate.connect(subscriber);
+}
+
+void AuthenticationModel::unsubscribe(connection_t subscriber)
+{
+ subscriber.disconnect();
+}
+
+/* setters */
+void AuthenticationModel::addAccount(const std::string &grid, const std::string &accountName,
+ const std::string &accountPassword)
+{
+ mAuthLLSD[grid][accountName] = LLSD::LLSD(accountPassword);
+ mEventUpdate();
+}
+
+void AuthenticationModel::removeAccount(const std::string &grid, const std::string &accountName)
+{
+ mAuthLLSD[grid].erase(accountName);
+ mEventUpdate();
+}
+
+void AuthenticationModel::changePassword(const std::string &grid, const std::string &accountName,
+ const std::string &newPassword)
+{
+ mAuthLLSD[grid][accountName] = newPassword;
+ // no event necessary: passwords aren't displayed in any view
+}
+
+/* getters */
+
+void AuthenticationModel::getAllAccountNames(std::list &names)
+{
+ // TODO: implement this for account management
+}
+
+void AuthenticationModel::getAccountNames(const std::string &grid, std::set &names)
+{
+ if(!mAuthLLSD.has(grid))
+ return;
+
+ for(LLSD::map_const_iterator it = mAuthLLSD[grid].beginMap();
+ it != mAuthLLSD[grid].endMap(); ++it)
+ {
+ names.insert(it->first);
+ }
+}
+
+void AuthenticationModel::getPassword(const std::string &grid, const std::string &accountName,
+ std::string &password)
+{
+ password = mAuthLLSD[grid][accountName].asString();
+}
+
+void AuthenticationModel::requestUpdate()
+{
+ mEventUpdate();
+}
diff --git a/linden/indra/newview/authentication_model.h b/linden/indra/newview/authentication_model.h
new file mode 100644
index 0000000..858e936
--- /dev/null
+++ b/linden/indra/newview/authentication_model.h
@@ -0,0 +1,53 @@
+/*
+ * authentication_model.h
+ * SecondLife
+ *
+ * Created by RMS on 7/17/08.
+ *
+ */
+
+#ifndef PL_authentication_model_H
+#define PL_authentication_model_H
+
+#include
+#include
+#include
+#include
+#include
+#include "lluuid.h"
+#include "llmemory.h"
+#include "llsd.h"
+
+class AuthenticationModel : public LLSingleton
+{
+public:
+ typedef boost::signal event_t;
+ typedef boost::signals::connection connection_t;
+
+ AuthenticationModel();
+ virtual ~AuthenticationModel();
+
+ void loadPersistentData();
+ void savePersistentData();
+ void revert();
+
+ /* generic update, pull model: */
+ connection_t subscribeToModelUpdates(event_t::slot_function_type subscriber);
+ void unsubscribe(connection_t subscriber);
+
+ /* setters */
+ void addAccount(const std::string &grid, const std::string &accountName, const std::string &accountPassword);
+ void removeAccount(const std::string &grid, const std::string &accountName);
+ void changePassword(const std::string &grid, const std::string &accountName, const std::string &newPassword);
+
+ /* getters */
+ void getAllAccountNames(std::list &names);
+ void getAccountNames(const std::string &grid, std::set &names);
+ void getPassword(const std::string &grid, const std::string &accountName, std::string &password);
+ void requestUpdate();
+protected:
+ LLSD mAuthLLSD;
+private:
+ event_t mEventUpdate;
+};
+#endif // PL_authentication_model_H
diff --git a/linden/indra/newview/controllerlogin.cpp b/linden/indra/newview/controllerlogin.cpp
new file mode 100644
index 0000000..9dd61a6
--- /dev/null
+++ b/linden/indra/newview/controllerlogin.cpp
@@ -0,0 +1,142 @@
+/*
+ * controllerlogin.cpp
+ * SecondLife
+ *
+ * Created by RMS on 7/16/08.
+ *
+ */
+#include "llerror.h"
+#include "llmd5.h"
+#include
+#include "controllerlogin.h"
+
+LoginController::LoginController(LoginFloater *floater, AuthenticationModel *authModel, const std::string &grid)
+: mFloater(floater), mModel(authModel), mGrid(grid)
+{
+ // set up the user interface subview pointers
+ name_combo = mFloater->getChild("name_combo");
+ password_edit = mFloater->getChild("password_edit");
+ start_location_combo= mFloater->getChild("start_location_combo");
+ remember_check = mFloater->getChild("remember_check");
+ connect_btn = mFloater->getChild("connect_btn");
+ quit_btn = mFloater->getChild("quit_btn");
+ server_combo = mFloater->getChild("server_combo");
+
+ // callbacks
+ // TODO: account creation and version information callbacks
+ name_combo->setCommitCallback(onCommitName);
+ name_combo->setCallbackUserData(this);
+ password_edit->setCommitCallback(onCommitPassword);
+ password_edit->setCallbackUserData(mFloater);
+ connect_btn->setClickedCallback(onAccept, this);
+ quit_btn->setClickedCallback(onCancel, this);
+
+ // subscribe to the model
+ mModelConnection = mModel->subscribeToModelUpdates(boost::bind(&LoginController::update, this));
+ // request an initial update
+ mModel->requestUpdate();
+}
+
+LoginController::~LoginController()
+{
+ mModel->unsubscribe(mModelConnection);
+}
+
+void LoginController::update()
+{
+ // when we want to update, we need to make sure it's relevant to our
+ // interests and make the change as smooth as possible for the user
+ std::set newAccountNames;
+ mModel->getAccountNames(mGrid, newAccountNames);
+
+ if(mAccountNames == newAccountNames)
+ return;
+
+ name_combo->removeall();
+
+ for(std::set::iterator it = newAccountNames.begin();
+ it != newAccountNames.end(); ++it)
+ {
+ name_combo->add(*it);
+ }
+
+ name_combo->sortByName();
+ mAccountNames.swap(newAccountNames);
+}
+
+void LoginController::mungePassword(std::string &password)
+{
+ LLMD5 pass((unsigned char *)password.c_str());
+ char munged_password[MD5HEX_STR_SIZE];
+ pass.hex_digest(munged_password);
+ password = munged_password;
+}
+
+// user interface callbacks
+
+void LoginController::onCommitName(LLUICtrl *control, void *userdata)
+{
+ // look at this shit it fills in the password box if it finds a stored account
+ // and auto checks remember password
+ LoginController *controller = (LoginController *)userdata;
+ LoginFloater *floater = controller->mFloater;
+
+ std::string loginname = floater->childGetText("name_combo");
+ std::set::iterator it = controller->mAccountNames.find(loginname);
+ if(it != controller->mAccountNames.end())
+ {
+ std::string loginpassword;
+
+ controller->mModel->getPassword(controller->mGrid, loginname, loginpassword);
+ LoginFloater::setFields(loginname, loginpassword, true);
+ }
+}
+
+void LoginController::onCommitPassword(LLUICtrl *control, void *userdata)
+{
+ LoginFloater *floater = (LoginFloater *)userdata;
+ LLLineEditor *editor = (LLLineEditor *)control;
+ std::string password = editor->getText();
+
+ // when we have a new password we need to MD5 it and tell the floater
+ if(!floater->isSamePassword(password))
+ {
+ mungePassword(password);
+ floater->setPassword(password);
+ }
+}
+
+void LoginController::onAccept(void* userdata)
+{
+ // this here does the main work of telling the model we need to write
+ // account data
+ LoginController *controller = (LoginController *)userdata;
+ LoginFloater *floater = controller->mFloater;
+
+ if(!floater->childGetValue("remember_check"))
+ {
+ LoginFloater::accept();
+ return;
+ }
+
+ std::string username = floater->childGetText("name_combo");
+ std::string password = floater->getPassword();
+
+ if(controller->mAccountNames.find(username) != controller->mAccountNames.end())
+ {
+ controller->mModel->changePassword(controller->mGrid, username, password);
+ }
+
+ else
+ {
+ controller->mModel->addAccount(controller->mGrid, username, password);
+ }
+ controller->mModel->savePersistentData();
+ LoginFloater::accept();
+}
+
+void LoginController::onCancel(void* userdata)
+{
+ // if the user backs out of the dialog we tell it to clean up and such
+ LoginFloater::cancel_old();
+}
diff --git a/linden/indra/newview/controllerlogin.h b/linden/indra/newview/controllerlogin.h
new file mode 100644
index 0000000..a187558
--- /dev/null
+++ b/linden/indra/newview/controllerlogin.h
@@ -0,0 +1,55 @@
+/*
+ * controllerlogin.h
+ * SecondLife
+ *
+ * Created by RMS on 7/16/08.
+ *
+ */
+#ifndef PL_controllerlogin_H
+#define PL_controllerlogin_H
+
+#include
+#include
+#include "llcombobox.h"
+#include "lllineeditor.h"
+#include "llcheckboxctrl.h"
+#include "llbutton.h"
+#include "floaterlogin.h"
+#include "authentication_model.h"
+
+class LoginController
+{
+public:
+ LoginController(LoginFloater *floater, AuthenticationModel *authModel, const std::string &grid);
+ virtual ~LoginController();
+ virtual void update();
+protected:
+ LoginFloater *mFloater;
+ AuthenticationModel *mModel;
+ std::string mGrid;
+private:
+ AuthenticationModel::connection_t mModelConnection;
+
+ static void mungePassword(std::string &password);
+
+ // UI subview pointers
+ LLComboBox *name_combo;
+ LLLineEditor *password_edit;
+ LLComboBox *start_location_combo;
+ LLCheckBoxCtrl *remember_check;
+ LLButton *connect_btn;
+ LLButton *quit_btn;
+ LLComboBox *server_combo;
+
+ // state
+ std::set mAccountNames;
+
+ // user interface callbacks
+ // TODO: find an alternative to linden callbacks
+ static void onCommitName(LLUICtrl *control, void *userdata);
+ static void onCommitPassword(LLUICtrl *control, void *userdata);
+ static void onAccept(void* userdata);
+ static void onCancel(void* userdata);
+};
+
+#endif // PL_controllerlogin_H
diff --git a/linden/indra/newview/controllerpasswords.cpp b/linden/indra/newview/controllerpasswords.cpp
new file mode 100644
index 0000000..6e39d9a
--- /dev/null
+++ b/linden/indra/newview/controllerpasswords.cpp
@@ -0,0 +1,41 @@
+/*
+ * controllerpasswords.cpp
+ * SecondLife
+ *
+ * Created by RMS on 8/5/08.
+ *
+ */
+
+#include "authentication_model.h"
+#include "prefpanelpasswords.h"
+#include "controllerpasswords.h"
+
+PasswordsController::PasswordsController(PasswordsPrefPanel *panel)
+: mPanel(panel)
+{
+ accounts_list = mPanel->getChild("accounts_list");
+ remove_btn = mPanel->getChild("remove_btn");
+ mModel = AuthenticationModel::getInstance();
+
+ // subscribe to the model
+ mModelConnection = mModel->subscribeToModelUpdates(boost::bind(&PasswordsController::update, this));
+ // request an initial update
+ mModel->requestUpdate();
+}
+
+PasswordsController::~PasswordsController()
+{
+ mModel->unsubscribe(mModelConnection);
+ mModel = NULL;
+}
+
+void PasswordsController::update()
+{
+ std::list newAccountData;
+ mModel->getAllAccountNames(newAccountData);
+
+ if(mAccountData == newAccountData)
+ return;
+
+ accounts_list->deleteAllItems();
+}
diff --git a/linden/indra/newview/controllerpasswords.h b/linden/indra/newview/controllerpasswords.h
new file mode 100644
index 0000000..e656659
--- /dev/null
+++ b/linden/indra/newview/controllerpasswords.h
@@ -0,0 +1,37 @@
+/*
+ * controllerpasswords.h
+ * SecondLife
+ *
+ * Created by RMS on 8/5/08.
+ *
+ */
+
+#include
+#include
+#include "llscrolllistctrl.h"
+#include "llbutton.h"
+#include "authentication_model.h"
+
+#ifndef PL_controllerpasswords_H
+#define PL_controllerpasswords_H
+class PasswordsPrefPanel;
+
+class PasswordsController
+{
+public:
+ PasswordsController(PasswordsPrefPanel *panel);
+ virtual ~PasswordsController();
+ virtual void update();
+protected:
+ LLScrollListCtrl *accounts_list;
+ LLButton *remove_btn;
+private:
+ AuthenticationModel::connection_t mModelConnection;
+
+ PasswordsPrefPanel *mPanel;
+ AuthenticationModel *mModel;
+
+ std::list mAccountData;
+};
+
+#endif // PL_controllerpasswords_H
diff --git a/linden/indra/newview/floaterlogin.cpp b/linden/indra/newview/floaterlogin.cpp
new file mode 100644
index 0000000..b943c4e
--- /dev/null
+++ b/linden/indra/newview/floaterlogin.cpp
@@ -0,0 +1,834 @@
+/*
+ * floaterlogin.cpp
+ * SecondLife
+ *
+ * Created by RMS on 7/15/08.
+ *
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include
+#include "llviewercontrol.h"
+#include "llviewerbuild.h"
+#include "llcombobox.h"
+#include "llscrolllistctrl.h"
+#include "llmd5.h"
+#include "llurlsimstring.h"
+#include "lluictrlfactory.h"
+#include "controllerlogin.h"
+#include "floaterlogin.h"
+#include "hippoGridManager.h"
+#include "llviewernetwork.h"
+#include "llpanellogin.h"
+
+#define PASSWORD_FILLER "123456789!123456"
+
+LoginFloater* LoginFloater::sInstance = NULL;
+LoginController* LoginFloater::sController = NULL;
+AuthenticationModel* LoginFloater::sModel = NULL;
+bool LoginFloater::sIsInitialLogin;
+std::string LoginFloater::sGrid;
+
+LoginFloater::LoginFloater(void (*callback)(S32 option, void* user_data),
+ void *cb_data)
+: LLFloater("floater_login"), mCallback(callback), mCallbackData(cb_data)
+{
+
+ mState = NORMAL;
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_login.xml");
+
+
+ llwarns << "LoginFloater called" << llendl;
+
+
+ // configure the floater interface for non-initial login
+ setCanMinimize(!sIsInitialLogin);
+ setCanClose(!sIsInitialLogin);
+ setCanDrag(!sIsInitialLogin);
+ childSetVisible("server_combo", sIsInitialLogin);
+
+ if(!sIsInitialLogin)
+ {
+ LLButton* quit_btn = getChild("quit_btn");
+ quit_btn->setLabel(std::string("Cancel"));
+ setTitle(std::string("Grid Manager"));
+ }
+
+ center();
+ LLLineEditor* edit = getChild("password_edit");
+ if (edit) edit->setDrawAsterixes(TRUE);
+ LLComboBox* combo = getChild("start_location_combo");
+ combo->setAllowTextEntry(TRUE, 128, FALSE);
+
+ BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
+ std::string sim_string = LLURLSimString::sInstance.mSimString;
+ if (!sim_string.empty())
+ {
+ // Replace "" with this region name
+ combo->remove(2);
+ combo->add( sim_string );
+ combo->setTextEntry(sim_string);
+ combo->setCurrentByIndex( 2 );
+ }
+ else if (login_last)
+ {
+ combo->setCurrentByIndex( 1 );
+ }
+ else
+ {
+ combo->setCurrentByIndex( 0 );
+ }
+
+ LLTextBox* version_text = getChild("version_text");
+ std::string version = llformat("%d.%d.%d (%d)",
+ LL_VERSION_MAJOR,
+ LL_VERSION_MINOR,
+ LL_VERSION_PATCH,
+ LL_VIEWER_BUILD );
+ version_text->setText(version);
+
+ LLTextBox* channel_text = getChild("channel_text");
+ channel_text->setText(gSavedSettings.getString("VersionChannelName"));
+
+ sendChildToBack(getChildView("channel_text"));
+ sendChildToBack(getChildView("version_text"));
+ sendChildToBack(getChildView("forgot_password_text"));
+
+ setDefaultBtn("connect_btn");
+
+
+
+}
+
+
+LoginFloater::~LoginFloater()
+{
+ delete LoginFloater::sController;
+
+ LoginFloater::sModel = NULL;
+ LoginFloater::sController = NULL;
+ LoginFloater::sInstance = NULL;
+}
+
+void LoginFloater::close()
+{
+ if(sInstance)
+ {
+ delete sInstance;
+ sInstance = NULL;
+ }
+}
+
+BOOL LoginFloater::postBuild()
+{
+ requires("grid_selector");
+ requires("gridnick");
+ requires("platform");
+ requires("gridname");
+ requires("loginuri");
+ requires("loginpage");
+ requires("helperuri");
+ requires("website");
+ requires("first_name");
+ requires("last_name");
+ requires("password");
+ //requires("search");
+ requires("btn_delete");
+ requires("btn_add");
+ requires("btn_copy");
+ requires("set_default");
+ requires("btn_gridinfo");
+ requires("btn_help_render_compat");
+ if (!checkRequirements()) return false;
+ LLLineEditor* password_edit = getChild("password");
+ if (password_edit) password_edit->setDrawAsterixes(TRUE);
+
+ childSetAction("btn_delete", onClickDelete, this);
+ childSetAction("btn_add", onClickAdd, this);
+ childSetAction("btn_copy", onClickCopy, this);
+ childSetAction("btn_apply", onClickApply, this);
+ childSetAction("set_default", onClickDefault, this);
+ childSetAction("btn_cancel", onClickCancel, this);
+//KOW childSetAction("set_default", onClickDefault, this);
+//KOW childSetAction("btn_gridinfo", onClickGridInfo, this);
+//KOW childSetAction("btn_help_render_compat", onClickHelpRenderCompat, this);
+
+ childSetCommitCallback("grid_selector", onSelectGrid, this);
+//KOW childSetCommitCallback("platform", onSelectPlatform, this);
+
+ // !!!### server_choice_combo->setFocusLostCallback(onServerComboLostFocus);
+
+//KOW update();
+ return TRUE;
+}
+
+void LoginFloater::refresh_grids()
+{
+ const std::string &defaultGrid = gHippoGridManager->getDefaultGridNick();
+ LLScrollListCtrl *grids = sInstance->getChild("grid_selector");
+ S32 selectIndex = -1, i = 0;
+ grids->deleteAllItems();
+ if (defaultGrid != "") {
+ LLSD value;
+ value["id"] = defaultGrid;
+ value["columns"][0]["column"] = "grid";
+ value["columns"][0]["value"] = defaultGrid;
+ grids->addElement(value);
+ selectIndex = i++;
+ }
+
+ HippoGridManager::GridIterator it, end = gHippoGridManager->endGrid();
+ for (it = gHippoGridManager->beginGrid(); it != end; ++it) {
+ const std::string &grid = it->second->getGridNick();
+ if (grid != defaultGrid) {
+ LLSD value;
+ value["id"] = grid;
+ value["columns"][0]["column"] = "grid";
+ value["columns"][0]["value"] = grid;
+ grids->addElement(value);
+
+ if (grid == sInstance->mCurGrid) selectIndex = i;
+ i++;
+ }
+ }
+ if ((sInstance->mState == ADD_NEW) || (sInstance->mState == ADD_COPY)) {
+ grids->addElement("");
+ selectIndex = i++;
+ }
+ if (selectIndex >= 0) {
+ //grids->setCurrentByIndex(selectIndex);
+ } else {
+ //grids->setLabel(LLStringExplicit("")); // LLComboBox::removeall() does not clear the label
+ }
+
+ sInstance->childSetTextArg("default_grid", "[DEFAULT]", (defaultGrid != "")? defaultGrid: " ");
+
+ sInstance->childSetEnabled("btn_delete", (selectIndex >= 0));
+ sInstance->childSetEnabled("btn_copy", (sInstance->mState == NORMAL) && (selectIndex >= 0));
+ sInstance->childSetEnabled("set_default", (sInstance->mState == NORMAL) && (selectIndex > 0));
+ sInstance->childSetEnabled("gridnick", (sInstance->mState == ADD_NEW) || (sInstance->mState == ADD_COPY));
+
+
+ LLComboBox *platform = sInstance->getChild("platform");
+ platform->removeall();
+ for (int p=HippoGridInfo::PLATFORM_OTHER; padd(HippoGridInfo::getPlatformString(static_cast(p)));
+
+
+ if (sInstance->mState == NORMAL) {
+ HippoGridInfo *gridInfo = gHippoGridManager->getGrid(sInstance->mCurGrid);
+ if (gridInfo) {
+ sInstance->childSetText("gridnick", gridInfo->getGridNick());
+ platform->setCurrentByIndex(gridInfo->getPlatform());
+ //sInstance->childSetText("grid_name", gridInfo->getGridName());
+ sInstance->childSetText("loginuri", gridInfo->getLoginUri());
+ sInstance->childSetText("loginpage", gridInfo->getLoginPage());
+ sInstance->childSetText("helperuri", gridInfo->getHelperUri());
+ sInstance->childSetText("website", gridInfo->getWebSite());
+ sInstance->childSetText("first_name", gridInfo->getFirstName());
+ sInstance->childSetText("last_name", gridInfo->getLastName());
+ if(gridInfo->getAvatarPassword().length() == 32)
+ sInstance->childSetText("password", std::string(PASSWORD_FILLER));
+ else if(gridInfo->getPasswordUrl().empty())
+ sInstance->childSetText("password", std::string(""));
+/*
+ if (gridInfo->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) {
+ //childSetEnabled("search", false);
+ //childSetText("search", LLStringExplicit(""));
+ childSetEnabled("render_compat", false);
+ childSetValue("render_compat", false);
+ } else {
+ //childSetEnabled("search", true);
+ //childSetText("search", gridInfo->getSearchUrl());
+ childSetEnabled("render_compat", true);
+ childSetValue("render_compat", gridInfo->isRenderCompat());
+ }
+ */
+ } else {
+ std::string empty = "";
+ sInstance->childSetText("gridnick", empty);
+ platform->setCurrentByIndex(HippoGridInfo::PLATFORM_OTHER);
+ sInstance->childSetText("gridname", empty);
+ sInstance->childSetText("loginuri", empty);
+ sInstance->childSetText("loginpage", empty);
+ sInstance->childSetText("helperuri", empty);
+ sInstance->childSetText("website", empty);
+ sInstance->childSetText("first_name", empty);
+ sInstance->childSetText("last_name", empty);
+ sInstance->childSetText("password", empty);
+ sInstance->childSetEnabled("render_compat", true);
+ sInstance->childSetValue("render_compat", true);
+ }
+ } else if (sInstance->mState == ADD_NEW) {
+ llwarns << "ADD_NEW" << llendl;
+ std::string required = "";
+ std::string empty = "";
+ sInstance->childSetText("gridnick", required);
+ platform->setCurrentByIndex(HippoGridInfo::PLATFORM_OTHER);
+ sInstance->childSetText("gridname", empty);
+ sInstance->childSetText("loginuri", required);
+ sInstance->childSetText("loginpage", empty);
+ sInstance->childSetText("helperuri", empty);
+ sInstance->childSetText("website", empty);
+ sInstance->childSetText("first_name", empty);
+ sInstance->childSetText("last_name", empty);
+ sInstance->childSetText("password", empty);
+ //childSetEnabled("search", true);
+ //childSetText("search", empty);
+ sInstance->childSetEnabled("render_compat", true);
+ sInstance->childSetValue("render_compat", true);
+ } else if (sInstance->mState == ADD_COPY) {
+ llwarns << "ADD_COPY" << llendl;
+ sInstance->childSetText("gridnick", LLStringExplicit(""));
+ } else {
+ llwarns << "Illegal state " << sInstance->mState << '.' << llendl;
+ }
+ return;
+}
+
+void LoginFloater::update()
+{
+ mState = NORMAL;
+ mCurGrid = gHippoGridManager->getCurrentGridNick();
+ refresh_grids();
+ //KOW gHippoLimits->setLimits();
+}
+
+void LoginFloater::applyChanges()
+{
+ HippoGridInfo *gridInfo = gHippoGridManager->getGrid(mCurGrid);
+ if (gridInfo)
+ {
+ if (gridInfo->getGridNick() == childGetValue("gridnick").asString())
+ {
+ gridInfo->setPlatform(childGetValue("platform"));
+ gridInfo->setGridName(childGetValue("gridname"));
+ gridInfo->setLoginUri(childGetValue("loginuri"));
+ gridInfo->setLoginPage(childGetValue("loginpage"));
+ gridInfo->setHelperUri(childGetValue("helperuri"));
+ gridInfo->setWebSite(childGetValue("website"));
+ gridInfo->setFirstName(childGetValue("first_name"));
+ gridInfo->setLastName(childGetValue("last_name"));
+ //gridInfo->setSearchUrl(childGetValue("search"));
+ gridInfo->setRenderCompat(childGetValue("render_compat"));
+
+ if(childGetValue("password").asString().empty())
+ gridInfo->setPasswordUrl(std::string(""));
+ else if(childGetValue("password").asString() != std::string(PASSWORD_FILLER))
+ {
+ // store account authentication data
+ std::string auth_password = childGetValue("password");
+ std::string hashed_password;
+ hashPassword(auth_password, hashed_password);
+ gridInfo->setAvatarPassword(hashed_password);
+ }
+ LLPanelLogin::setFields(gridInfo->getFirstName(), gridInfo->getLastName(),
+ gridInfo->getAvatarPassword(), true);
+ }
+ else
+ {
+ llwarns << "Grid nickname mismatch, ignoring changes." << llendl;
+ }
+ }
+}
+
+
+bool LoginFloater::createNewGrid()
+{
+ // check nickname
+ std::string gridnick = childGetValue("gridnick");
+ if (gridnick == "") gridnick = "";
+ HippoGridInfo::cleanUpGridNick(gridnick);
+ childSetValue("gridnick", (gridnick != "")? gridnick: "");
+ if (gridnick == "") {
+ //KOW gViewerWindow->alertXml("GridsNoNick");
+ return false;
+ }
+ if (gHippoGridManager->getGrid(gridnick)) {
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = gridnick;
+ //KOW gViewerWindow->alertXml("GridExists", args);
+ return false;
+ }
+
+ // check login URI
+ std::string loginuri = childGetValue("loginuri");
+ if ((loginuri == "") || (loginuri == "")) {
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = gridnick;
+ //KOW gViewerWindow->alertXml("GridsNoLoginUri", args);
+ return false;
+ }
+
+ // create new grid
+ HippoGridInfo *grid = new HippoGridInfo(gridnick);
+ grid->setPlatform(childGetValue("platform"));
+ grid->setGridName(childGetValue("gridname"));
+ grid->setLoginUri(loginuri);
+ grid->setLoginPage(childGetValue("loginpage"));
+ grid->setHelperUri(childGetValue("helperuri"));
+ grid->setWebSite(childGetValue("website"));
+ grid->setFirstName(childGetValue("first_name"));
+ grid->setLastName(childGetValue("last_name"));
+ //grid->setSearchUrl(childGetValue("search"));
+ grid->setRenderCompat(childGetValue("render_compat"));
+ gHippoGridManager->addGrid(grid);
+
+ if(childGetValue("password").asString().empty())
+ grid->setAvatarPassword(std::string(""));
+ else
+ {
+ std::string hashed_password;
+ hashPassword(childGetValue("password"), hashed_password);
+ grid->setAvatarPassword(hashed_password);
+ }
+
+ mCurGrid = gridnick;
+ return true;
+}
+
+void LoginFloater::apply()
+{
+ if (mState == NORMAL) {
+ applyChanges();
+ } else if ((mState == ADD_NEW) || (mState == ADD_COPY)) {
+ if (!createNewGrid()) return;
+ } else {
+ llwarns << "Illegal state " << mState << '.' << llendl;
+ return;
+ }
+ //gHippoGridManager->setCurrentGrid(mCurGrid);
+ //gHippoGridManager->setDefaultGrid(mCurGrid);
+ //LLPanelLogin::refreshLoginPage();
+ gHippoGridManager->saveFile();
+ LLPanelLogin::addServer(LLViewerLogin::getInstance()->getGridLabel());
+}
+
+void LoginFloater::setDefault()
+{
+ if (mState == NORMAL) {
+ applyChanges();
+ } else if ((mState == ADD_NEW) || (mState == ADD_COPY)) {
+ if (!createNewGrid()) return;
+ } else {
+ llwarns << "Illegal state " << mState << '.' << llendl;
+ return;
+ }
+ gHippoGridManager->setCurrentGrid(mCurGrid);
+ gHippoGridManager->setDefaultGrid(mCurGrid);
+ llwarns << "I think me grid is " << mCurGrid << llendl;
+ //LLPanelLogin::refreshLoginPage();
+ gHippoGridManager->saveFile();
+ LLPanelLogin::addServer(LLViewerLogin::getInstance()->getGridLabel());
+}
+
+void LoginFloater::cancel()
+{
+ gHippoGridManager->discardAndReload();
+ LoginFloater::sModel->revert();
+ update();
+}
+
+void LoginFloater::onSelectGrid(LLUICtrl* ctrl, void *data)
+{
+ LoginFloater* self = (LoginFloater*)data;
+ if (self->mState == NORMAL) {
+ self->applyChanges();
+ } else if ((self->mState == ADD_NEW) || (self->mState == ADD_COPY)) {
+ if (self->createNewGrid()) {
+ self->mState = NORMAL;
+ } else {
+ //LLCtrlListInterface *grids = self->childGetListInterface("search_results");
+ //if (!grids) return;
+
+ //LLSD selected_value = grids->getSelectedValue();
+ //std::string sim_name = selected_value.asString();
+
+ LLComboBox *grids = self->getChild("grid_selector");
+ grids->setCurrentByIndex(grids->getItemCount() - 1);
+ return;
+ }
+ } else {
+ llwarns << "Illegal state " << self->mState << '.' << llendl;
+ return;
+ }
+ self->mCurGrid = ctrl->getValue().asString();
+ llwarns << "I think me grid is " << self->mCurGrid << llendl;
+
+ self->refresh_grids();
+}
+
+//static
+void LoginFloater::onClickDelete(void *data)
+{
+ llwarns << "onclickdelete" << llendl;
+ LoginFloater* self = (LoginFloater*)data;
+ if (self->mState == NORMAL)
+ gHippoGridManager->deleteGrid(self->mCurGrid);
+ self->update();
+}
+
+//static
+void LoginFloater::onClickAdd(void *data)
+{
+ llwarns << "add" << llendl;
+ LoginFloater* self = (LoginFloater*)data;
+ self->mState = ADD_NEW;
+ self->refresh_grids();
+}
+
+
+//static
+void LoginFloater::onClickCopy(void *data)
+{
+ llwarns << "copy" << llendl;
+ LoginFloater* self = (LoginFloater*)data;
+ self->mState = ADD_COPY;
+ self->refresh_grids();
+}
+
+//static
+void LoginFloater::onClickApply(void *data)
+{
+ sInstance->apply();
+}
+
+//static
+void LoginFloater::onClickDefault(void *data)
+{
+ sInstance->setDefault();
+}
+
+//static
+void LoginFloater::onClickCancel(void *data)
+{
+ sInstance->cancel();
+}
+
+void LoginFloater::setAlwaysRefresh(bool refresh)
+{
+ // wargames 2: dead code, LLPanelLogin compatibility
+ return;
+}
+
+void LoginFloater::refreshLocation( bool force_visible )
+{
+
+ llwarns << "refreshLocation called" << llendl;
+
+ if (!sInstance) return;
+
+ LLComboBox* combo = sInstance->getChild("start_location_combo");
+
+ if (LLURLSimString::parse())
+ {
+ combo->setCurrentByIndex( 3 ); // BUG? Maybe 2?
+ combo->setTextEntry(LLURLSimString::sInstance.mSimString);
+ }
+ else
+ {
+ BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation");
+ combo->setCurrentByIndex( login_last ? 1 : 0 );
+ }
+
+ BOOL show_start = TRUE;
+
+ if ( ! force_visible )
+ show_start = gSavedSettings.getBOOL("ShowStartLocation");
+
+ sInstance->childSetVisible("start_location_combo", show_start);
+ sInstance->childSetVisible("start_location_text", show_start);
+ sInstance->childSetVisible("server_combo", TRUE);
+}
+
+void LoginFloater::newShow(const std::string &grid, bool initialLogin,
+ void (*callback)(S32 option, void* user_data),
+ void* callback_data)
+{
+
+ llwarns << "newShow called" << llendl;
+ if(NULL==sInstance)
+ {
+ LoginFloater::sGrid = grid;
+ LoginFloater::sIsInitialLogin = initialLogin;
+ sInstance = new LoginFloater(callback, callback_data);
+
+ llwarns << "sInstance assigned. sInstance=" << sInstance << llendl;
+ }
+
+ // floater controller requires initialized floater and model
+ if(NULL==sModel)
+ sModel = AuthenticationModel::getInstance();
+ if(NULL==sController)
+ //sController = new LoginController(sInstance, sModel, sGrid);
+
+
+
+ llwarns << "newshow called" << llendl;
+ sInstance->mCurGrid = gHippoGridManager->getCurrentGridNick();
+ refresh_grids();
+
+ // we're important
+ sInstance->setFrontmost(TRUE);
+ sInstance->setFocus(TRUE);
+
+}
+
+void LoginFloater::testShow(void *lies)
+{
+ // this is if we want to call LoginFloater from a menu option
+ // or you know whatever
+ newShow(std::string("Test"), false, testCallback, NULL);
+}
+
+void LoginFloater::testCallback(S32 option, void *user_data)
+{
+ // test callback, referenced by testShow()
+ if(LOGIN_OPTION_CONNECT == option)
+ {
+ llinfos << "this is how we connect to a METAVERSE" << llendl;
+ std::string first, last, password;
+ BOOL remember = TRUE;
+ getFields(first, last, password, remember);
+ llinfos << "first\t\tlast\t\tpassword" << llendl;
+ llinfos << first << "\t\t" << last << "\t\t" << password << llendl;
+ }
+ else if(LOGIN_OPTION_QUIT == option)
+ {
+ llinfos << "my login, she die" << llendl;
+ llinfos << ":(" << llendl;
+ close();
+ }
+}
+
+void LoginFloater::show(const LLRect &rect, BOOL show_server,
+ void (*callback)(S32 option, void* user_data),
+ void* callback_data)
+{
+ // we don't need a grid passed in because this is old-style login
+ std::string grid = "";
+ newShow(grid, TRUE, callback, callback_data);
+}
+
+void LoginFloater::setFocus(BOOL b)
+{
+ if(b != hasFocus())
+ {
+ if(b)
+ {
+ LoginFloater::giveFocus();
+ }
+ else
+ {
+ LLPanel::setFocus(b);
+ }
+ }
+}
+
+void LoginFloater::giveFocus()
+{
+ LLComboBox *combo = NULL;
+
+ if(NULL==sInstance)
+ {
+ llwarns << "giveFocus has no LoginFloater instance. sInstance=" << sInstance << llendl;
+ return;
+ }
+
+ // for our combo box approach, selecting the combo box is almost always
+ // the right thing to do on the floater receiving focus
+ combo = sInstance->getChild("name_combo");
+ combo->setFocus(TRUE);
+}
+
+void LoginFloater::getFields(std::string &firstname, std::string &lastname, std::string &password,
+ BOOL &remember)
+{
+ if (!sInstance)
+ {
+ llwarns << "Attempted getFields with no login view shown" << llendl;
+ return;
+ }
+
+ std::string loginname = sInstance->childGetText("name_combo");
+
+ LLStringUtil::replaceTabsWithSpaces(loginname, 1);
+ LLStringUtil::trim(loginname);
+ std::vector loginVec;
+ boost::split(loginVec, loginname, boost::is_any_of(" "), boost::token_compress_on);
+ if(loginVec.size() == 2)
+ {
+ firstname = loginVec[0];
+ lastname = loginVec[1];
+ }
+
+ password = sInstance->mMungedPassword;
+ remember = sInstance->childGetValue("remember_check");
+}
+
+void LoginFloater::getFields(std::string &loginname, std::string &password, BOOL &remember)
+{
+ std::string first, last, pass;
+ BOOL rem;
+ getFields(first, last, pass, rem);
+ loginname = first + " " + last;
+ password = pass;
+ remember = rem;
+}
+
+void LoginFloater::setFields(const std::string& firstname, const std::string& lastname, const std::string& password,
+ BOOL remember)
+{
+ if (!sInstance)
+ {
+ llwarns << "Attempted setFields with no login view shown" << llendl;
+ return;
+ }
+
+ std::string loginname = firstname + " " + lastname;
+ sInstance->childSetText("name_combo", loginname);
+
+ // Max "actual" password length is 16 characters.
+ // Hex digests are always 32 characters.
+ if (password.length() == 32)
+ {
+ // This is a MD5 hex digest of a password.
+ // We don't actually use the password input field,
+ // fill it with MAX_PASSWORD characters so we get a
+ // nice row of asterixes.
+ const std::string filler("123456789!123456");
+ sInstance->childSetText("password_edit", filler);
+ sInstance->mIncomingPassword = filler;
+ sInstance->mMungedPassword = password;
+ }
+ else
+ {
+ // this is a normal text password
+ sInstance->childSetText("password_edit", password);
+ sInstance->mIncomingPassword = password;
+ LLMD5 pass((unsigned char *)password.c_str());
+ char munged_password[MD5HEX_STR_SIZE];
+ pass.hex_digest(munged_password);
+ sInstance->mMungedPassword = munged_password;
+ }
+
+ sInstance->childSetValue("remember_check", remember);
+}
+
+void LoginFloater::setFields(const std::string &loginname, const std::string &password, BOOL remember)
+{
+ std::vector loginVec;
+ boost::split(loginVec, loginname, boost::is_any_of(" "), boost::token_compress_on);
+ setFields(loginVec[0], loginVec[1], password, remember);
+}
+
+BOOL LoginFloater::isGridComboDirty()
+{
+ BOOL user_picked = FALSE;
+ if (!sInstance)
+ {
+ llwarns << "Attempted getServer with no login view shown" << llendl;
+ }
+ else
+ {
+ LLComboBox* combo = sInstance->getChild("server_combo");
+ user_picked = combo->isDirty();
+ }
+ return user_picked;
+}
+
+void LoginFloater::getLocation(std::string &location)
+{
+ if (!sInstance)
+ {
+ llwarns << "Attempted getLocation with no login view shown" << llendl;
+ return;
+ }
+
+ LLComboBox* combo = sInstance->getChild("start_location_combo");
+ location = combo->getValue().asString();
+}
+
+std::string& LoginFloater::getPassword()
+{
+ return mMungedPassword;
+}
+
+void LoginFloater::setPassword(std::string &password)
+{
+ mMungedPassword = password;
+}
+
+bool LoginFloater::isSamePassword(std::string &password)
+{
+ return mMungedPassword == password;
+}
+
+void LoginFloater::addServer(const std::string& server, S32 domain_name)
+{
+ if (!sInstance)
+ {
+ llwarns << "Attempted addServer with no login view shown" << llendl;
+ return;
+ }
+
+ LLComboBox* combo = sInstance->getChild("server_combo");
+ combo->add(server, LLSD(domain_name) );
+ combo->setCurrentByIndex(0);
+}
+
+void LoginFloater::accept()
+{
+ if(NULL==sInstance || NULL==sInstance->mCallback)
+ return;
+
+ sInstance->setFocus(FALSE);
+
+ std::string name_combo = sInstance->childGetText("name_combo");
+ if(!name_combo.empty())
+ {
+ sInstance->mCallback(LOGIN_OPTION_CONNECT, sInstance->mCallbackData);
+ }
+ else
+ {
+ // TODO: new account call goes here
+ return;
+ }
+}
+
+void LoginFloater::cancel_old()
+{
+ if(NULL==sInstance)
+ return;
+
+ if(sInstance->sIsInitialLogin)
+ {
+ // send a callback that indicates we're quitting or closing
+ if(sInstance->mCallback)
+ sInstance->mCallback(LOGIN_OPTION_QUIT, sInstance->mCallbackData);
+ return;
+ }
+
+ sInstance->close();
+}
+
+void LoginFloater::hashPassword(const std::string& password, std::string& hashedPassword)
+{
+ // Max "actual" password length is 16 characters.
+ // Hex digests are always 32 characters.
+ if (password.length() == 32)
+ {
+ hashedPassword = password;
+ }
+ else
+ {
+ // this is a normal text password
+ LLMD5 pass((unsigned char *)password.c_str());
+ char munged_password[MD5HEX_STR_SIZE];
+ pass.hex_digest(munged_password);
+ hashedPassword = munged_password;
+ }
+
+}
+
diff --git a/linden/indra/newview/floaterlogin.h b/linden/indra/newview/floaterlogin.h
new file mode 100644
index 0000000..1800897
--- /dev/null
+++ b/linden/indra/newview/floaterlogin.h
@@ -0,0 +1,98 @@
+/*
+ * floaterlogin.h
+ * SecondLife
+ *
+ * Created by RMS on 7/15/08.
+ *
+ */
+#ifndef PL_floaterlogin_H
+#define PL_floaterlogin_H
+
+#define LOGIN_OPTION_CONNECT 0
+#define LOGIN_OPTION_QUIT 1
+
+#include "llfloater.h"
+
+class LoginController;
+class AuthenticationModel;
+
+class LoginFloater : public LLFloater
+{
+public:
+ LoginFloater(void (*callback)(S32 option, void *user_data),
+ void *callback_data);
+ virtual ~LoginFloater();
+
+ virtual BOOL postBuild();
+
+ static void refresh_grids();
+ void apply();
+ void setDefault();
+ void cancel();
+
+ // new-style login methods
+ static void newShow(const std::string &grid, bool initialLogin,
+ void (*callback)(S32 option, void *user_data),
+ void *callback_data);
+ static void testShow(void *lies);
+ static void testCallback(S32 option, void *user_data);
+ virtual std::string& getPassword();
+ virtual void setPassword(std::string &password);
+ virtual bool isSamePassword(std::string &password);
+ static void getFields(std::string &loginname, std::string &password,
+ BOOL &remember);
+ static void setFields(const std::string &loginname, const std::string &password,
+ BOOL remember);
+
+ // LLLoginPanel compatibility
+ //TODO: Make this not suck
+ static void show(const LLRect &rect, BOOL show_server,
+ void (*callback)(S32 option, void *user_data),
+ void *callback_data);
+ static void close();
+ static void setAlwaysRefresh(bool refresh);
+ static void refreshLocation(bool force_visible);
+ virtual void setFocus(BOOL b);
+ static void giveFocus();
+ static void getFields(std::string& firstname, std::string& lastname,
+ std::string& password, BOOL& remember);
+ static void setFields(const std::string& firstname, const std::string &lastname,
+ const std::string& password, BOOL remember);
+ static void getLocation(std::string &location);
+ static BOOL isGridComboDirty();
+ static void addServer(const std::string& server, S32 domain_name);
+ static void accept();
+ static void cancel_old();
+ static void hashPassword(const std::string& password, std::string& hashedPassword);
+protected:
+ static bool sIsInitialLogin;
+ static std::string sGrid;
+private:
+ enum State { NORMAL, ADD_NEW, ADD_COPY };
+ State mState;
+ std::string mCurGrid;
+
+ std::string mIncomingPassword;
+ std::string mMungedPassword;
+
+ void applyChanges();
+ bool createNewGrid();
+ void update();
+
+ static void onSelectGrid(LLUICtrl *ctrl, void *data);
+ static void onClickDelete(void *data);
+ static void onClickAdd(void *data);
+ static void onClickCopy(void *data);
+ static void onClickApply(void *data);
+ static void onClickDefault(void *data);
+ static void onClickCancel(void *data);
+
+ static LoginFloater *sInstance;
+ static LoginController *sController;
+ static AuthenticationModel *sModel;
+
+ void (*mCallback)(S32 option, void *userdata);
+ void *mCallbackData;
+};
+
+#endif // PL_floaterlogin_H
diff --git a/linden/indra/newview/hippoGridManager.cpp b/linden/indra/newview/hippoGridManager.cpp
new file mode 100644
index 0000000..8415adb
--- /dev/null
+++ b/linden/indra/newview/hippoGridManager.cpp
@@ -0,0 +1,597 @@
+
+
+#include "hippoGridManager.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "llviewercontrol.h"
+#include "llweb.h"
+
+#include "hippoRestRequest.h"
+
+
+// ********************************************************************
+// Global Variables
+
+HippoGridManager *gHippoGridManager = 0;
+
+HippoGridInfo HippoGridInfo::FALLBACK_GRIDINFO("");
+
+
+
+// ********************************************************************
+// ********************************************************************
+// HippoGridInfo
+// ********************************************************************
+// ********************************************************************
+
+
+// ********************************************************************
+// Initialize
+
+HippoGridInfo::HippoGridInfo(const std::string &gridNick) :
+ mPlatform(PLATFORM_OTHER),
+ mGridNick(gridNick),
+ mRenderCompat(true),
+ mCurrencySymbol("OS$"),
+ mRealCurrencySymbol("US$"),
+ mDirectoryFee(30)
+{
+ cleanUpGridNick(mGridNick);
+}
+
+
+void HippoGridInfo::setPlatform(Platform platform)
+{
+ mPlatform = platform;
+ mCurrencySymbol = (mPlatform == PLATFORM_SECONDLIFE)? "L$": "OS$";
+}
+
+
+void HippoGridInfo::setPlatform(const std::string &platform)
+{
+ std::string tmp = platform;
+ for (unsigned i=0; imXmlState = XML_GRIDNICK;
+ else if (strcasecmp(name, "gridname") == 0)
+ self->mXmlState = XML_GRIDNAME;
+ else if (strcasecmp(name, "platform") == 0)
+ self->mXmlState = XML_PLATFORM;
+ else if ((strcasecmp(name, "login") == 0) || (strcasecmp(name, "loginuri") == 0))
+ self->mXmlState = XML_LOGINURI;
+ else if ((strcasecmp(name, "welcome") == 0) || (strcasecmp(name, "loginpage") == 0))
+ self->mXmlState = XML_LOGINPAGE;
+ else if ((strcasecmp(name, "economy") == 0) || (strcasecmp(name, "helperuri") == 0))
+ self->mXmlState = XML_HELPERURI;
+ else if ((strcasecmp(name, "about") == 0) || (strcasecmp(name, "website") == 0))
+ self->mXmlState = XML_WEBSITE;
+ else if ((strcasecmp(name, "help") == 0) || (strcasecmp(name, "support") == 0))
+ self->mXmlState = XML_SUPPORT;
+ else if ((strcasecmp(name, "register") == 0) || (strcasecmp(name, "account") == 0))
+ self->mXmlState = XML_REGISTER;
+ else if (strcasecmp(name, "password") == 0)
+ self->mXmlState = XML_PASSWORD;
+ //else if (strcasecmp(name, "search") == 0)
+ //self->mXmlState = XML_SEARCH;
+}
+
+//static
+void HippoGridInfo::onXmlElementEnd(void *userData, const XML_Char *name)
+{
+ HippoGridInfo *self = (HippoGridInfo*)userData;
+ self->mXmlState = XML_VOID;
+}
+
+//static
+void HippoGridInfo::onXmlCharacterData(void *userData, const XML_Char *s, int len)
+{
+ HippoGridInfo *self = (HippoGridInfo*)userData;
+ switch (self->mXmlState) {
+
+ case XML_GRIDNICK:
+ if (self->mGridNick == "") self->mGridNick.assign(s, len);
+ cleanUpGridNick(self->mGridNick);
+ break;
+
+ case XML_PLATFORM: {
+ std::string platform(s, len);
+ self->setPlatform(platform);
+ break;
+ }
+
+ case XML_LOGINURI:
+ self->mLoginUri.assign(s, len);
+ cleanUpUri(self->mLoginUri);
+ break;
+
+ case XML_HELPERURI:
+ self->mHelperUri.assign(s, len);
+ cleanUpUri(self->mHelperUri);
+ break;
+
+ case XML_SEARCH:
+ //self->mSearchUrl.assign(s, len);
+ //cleanUpQueryUrl(mSearchUrl);
+ break;
+
+ case XML_GRIDNAME: self->mGridName.assign(s, len); break;
+ case XML_LOGINPAGE: self->mLoginPage.assign(s, len); break;
+ case XML_WEBSITE: self->mWebSite.assign(s, len); break;
+ case XML_SUPPORT: self->mSupportUrl.assign(s, len); break;
+ case XML_REGISTER: self->mRegisterUrl.assign(s, len); break;
+ case XML_PASSWORD: self->mPasswordUrl.assign(s, len); break;
+
+ case XML_VOID: break;
+ }
+}
+
+
+bool HippoGridInfo::retrieveGridInfo()
+{
+ if (mLoginUri == "") return false;
+
+ std::string reply;
+ int result = HippoRestRequest::getBlocking(mLoginUri + "get_grid_info", &reply);
+ if (result != 200) return false;
+
+ llinfos << "Received: " << reply << llendl;
+
+ bool success = true;
+ XML_Parser parser = XML_ParserCreate(0);
+ XML_SetUserData(parser, this);
+ XML_SetElementHandler(parser, onXmlElementStart, onXmlElementEnd);
+ XML_SetCharacterDataHandler(parser, onXmlCharacterData);
+ mXmlState = XML_VOID;
+ if (!XML_Parse(parser, reply.data(), reply.size(), TRUE)) {
+ llwarns << "XML Parse Error: " << XML_ErrorString(XML_GetErrorCode(parser)) << llendl;
+ success = false;
+ }
+ XML_ParserFree(parser);
+
+ return success;
+}
+
+
+std::string HippoGridInfo::getUploadFee() const
+{
+ std::string fee;
+ formatFee(fee, LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), true);
+ return fee;
+}
+
+std::string HippoGridInfo::getGroupCreationFee() const
+{
+ std::string fee;
+ formatFee(fee, LLGlobalEconomy::Singleton::getInstance()->getPriceGroupCreate(), false);
+ return fee;
+}
+
+std::string HippoGridInfo::getDirectoryFee() const
+{
+ std::string fee;
+ formatFee(fee, mDirectoryFee, true);
+ if (fee != "free") fee += "/week";
+ return fee;
+}
+
+void HippoGridInfo::formatFee(std::string &fee, int cost, bool showFree) const
+{
+ if (showFree && (cost == 0)) {
+ fee = "free";
+ } else {
+ fee = llformat("%s%d", getCurrencySymbol().c_str(), cost);
+ }
+}
+
+
+// ********************************************************************
+// Static Helpers
+
+// static
+const char *HippoGridInfo::getPlatformString(Platform platform)
+{
+ static const char *platformStrings[PLATFORM_LAST] = {
+ "Other", "OpenSim", "SecondLife"
+ };
+
+ if ((platform < PLATFORM_OTHER) || (platform >= PLATFORM_LAST))
+ platform = PLATFORM_OTHER;
+ return platformStrings[platform];
+}
+
+
+// static
+void HippoGridInfo::cleanUpGridNick(std::string &gridnick)
+{
+ std::string tmp;
+ int size = gridnick.size();
+ for (int i=0; i::iterator it, end = mGridInfo.end();
+ for (it=mGridInfo.begin(); it != end; ++it) {
+ delete it->second;
+ }
+ mGridInfo.clear();
+}
+
+
+void HippoGridManager::init()
+{
+ HippoGridInfo::initFallback();
+ loadFromFile();
+
+ // !!!### gSavedSettings.getControl("CmdLineLoginURI");
+ // !!!### gSavedSettings.getString("CmdLineLoginPage");
+ // !!!### gSavedSettings.getString("CmdLineHelperURI");
+ // !!!### LLString::compareInsensitive(gGridInfo[grid_index].mLabel, grid_name.c_str()))
+}
+
+
+void HippoGridManager::discardAndReload()
+{
+ cleanup();
+ loadFromFile();
+}
+
+
+// ********************************************************************
+// Public Access
+
+HippoGridInfo *HippoGridManager::getGrid(const std::string &grid) const
+{
+ std::map::const_iterator it;
+ it = mGridInfo.find(grid);
+ if (it != mGridInfo.end()) {
+ return it->second;
+ } else {
+ return 0;
+ }
+}
+
+
+HippoGridInfo *HippoGridManager::getCurrentGrid() const
+{
+ HippoGridInfo *grid = getGrid(mCurrentGrid);
+ if (grid) {
+ return grid;
+ } else {
+ return &HippoGridInfo::FALLBACK_GRIDINFO;
+ }
+}
+
+
+void HippoGridManager::addGrid(HippoGridInfo *grid)
+{
+ if (!grid) return;
+ const std::string &nick = grid->getGridNick();
+ if (nick == "") {
+ llwarns << "Ignoring to try adding grid with empty nick." << llendl;
+ delete grid;
+ return;
+ }
+ if (mGridInfo.find(nick) != mGridInfo.end()) {
+ llwarns << "Ignoring to try adding existing grid " << nick << '.' << llendl;
+ delete grid;
+ return;
+ }
+ mGridInfo[nick] = grid;
+}
+
+
+void HippoGridManager::deleteGrid(const std::string &grid)
+{
+ GridIterator it = mGridInfo.find(grid);
+ if (it == mGridInfo.end()) {
+ llwarns << "Trying to delete non-existing grid " << grid << '.' << llendl;
+ return;
+ }
+ mGridInfo.erase(it);
+ llinfos << "Number of grids now: " << mGridInfo.size() << llendl;
+ if (mGridInfo.empty()) llinfos << "Grid info map is empty." << llendl;
+ if (grid == mDefaultGrid)
+ setDefaultGrid(""); // sets first grid, if map not empty
+ if (grid == mCurrentGrid)
+ mCurrentGrid = mDefaultGrid;
+}
+
+
+void HippoGridManager::setDefaultGrid(const std::string &grid)
+{
+ GridIterator it = mGridInfo.find(grid);
+ if (it != mGridInfo.end()) {
+ mDefaultGrid = grid;
+ } else if (mGridInfo.find("secondlife") != mGridInfo.end()) {
+ mDefaultGrid = "secondlife";
+ } else if (!mGridInfo.empty()) {
+ mDefaultGrid = mGridInfo.begin()->first;
+ } else {
+ mDefaultGrid = "";
+ }
+}
+
+
+void HippoGridManager::setCurrentGrid(const std::string &grid)
+{
+ GridIterator it = mGridInfo.find(grid);
+ if (it != mGridInfo.end()) {
+ mCurrentGrid = grid;
+ } else if (!mGridInfo.empty()) {
+ llwarns << "Unknown grid '" << grid << "'. Setting to default grid." << llendl;
+ mCurrentGrid = mDefaultGrid;
+ }
+}
+
+
+// ********************************************************************
+// Persistent Store
+
+void HippoGridManager::loadFromFile()
+{
+ mDefaultGridsVersion = 0;
+ // load user grid info
+ parseFile(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "grid_info.xml"), false);
+ // merge default grid info, if newer. Force load, if list of grids is empty.
+ parseFile(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "default_grids.xml"), !mGridInfo.empty());
+ // merge grid info from web site, if newer. Force load, if list of grids is empty.
+ if (gSavedSettings.getBOOL("CheckForGridUpdates"))
+ parseUrl("http://opensim-viewer.sourceforge.net/db/grids.php", !mGridInfo.empty());
+
+ setDefaultGrid(gSavedSettings.getString("DefaultGrid"));
+ setCurrentGrid(gSavedSettings.getString("CmdLineGridChoice"));
+}
+
+
+void HippoGridManager::parseUrl(const char *url, bool mergeIfNewer)
+{
+ llinfos << "Loading grid info from '" << url << "'." << llendl;
+
+ // query update server
+ std::string escaped_url = LLWeb::escapeURL(url);
+ LLSD response = LLHTTPClient::blockingGet(url);
+
+ // check response, return on error
+ S32 status = response["status"].asInteger();
+ if ((status != 200) || !response["body"].isArray()) {
+ llinfos << "GridInfo Update failed (" << status << "): "
+ << (response["body"].isString()? response["body"].asString(): "")
+ << llendl;
+ return;
+ }
+
+ LLSD gridInfo = response["body"];
+ parseData(gridInfo, mergeIfNewer);
+}
+
+void HippoGridManager::parseFile(const std::string &fileName, bool mergeIfNewer)
+{
+ llifstream infile;
+ infile.open(fileName.c_str());
+ if(!infile.is_open()) {
+ llwarns << "Cannot find grid info file " << fileName << " to load." << llendl;
+ return;
+ }
+
+ LLSD gridInfo;
+ if (LLSDSerialize::fromXML(gridInfo, infile) <= 0) {
+ llwarns << "Unable to parse grid info file " << fileName << '.' << llendl;
+ return;
+ }
+
+ llinfos << "Loading grid info file " << fileName << '.' << llendl;
+ parseData(gridInfo, mergeIfNewer);
+}
+
+
+void HippoGridManager::parseData(LLSD &gridInfo, bool mergeIfNewer)
+{
+ if (mergeIfNewer) {
+ LLSD::array_const_iterator it, end = gridInfo.endArray();
+ for (it = gridInfo.beginArray(); it != end; ++it) {
+ LLSD gridMap = *it;
+ if (gridMap.has("default_grids_version")) {
+ int version = gridMap["default_grids_version"];
+ if (version <= mDefaultGridsVersion) return;
+ else break;
+ }
+ }
+ if (it == end) {
+ llwarns << "Grid data has no version number." << llendl;
+ return;
+ }
+ }
+
+ llinfos << "Loading grid data." << llendl;
+
+ LLSD::array_const_iterator it, end = gridInfo.endArray();
+ for (it = gridInfo.beginArray(); it != end; ++it) {
+ LLSD gridMap = *it;
+ if (gridMap.has("default_grids_version")) {
+ mDefaultGridsVersion = gridMap["default_grids_version"];
+ } else if (gridMap.has("gridnick") && gridMap.has("loginuri")) {
+ std::string gridnick = gridMap["gridnick"];
+ HippoGridInfo *grid;
+ GridIterator it = mGridInfo.find(gridnick);
+ bool newGrid = (it == mGridInfo.end());
+ if (newGrid) {
+ // create new grid info
+ grid = new HippoGridInfo(gridnick);
+ } else {
+ // update existing grid info
+ grid = it->second;
+ }
+ grid->setLoginUri(gridMap["loginuri"]);
+ if (gridMap.has("platform")) grid->setPlatform(gridMap["platform"]);
+ if (gridMap.has("gridname")) grid->setGridName(gridMap["gridname"]);
+ if (gridMap.has("loginpage")) grid->setLoginPage(gridMap["loginpage"]);
+ if (gridMap.has("helperuri")) grid->setHelperUri(gridMap["helperuri"]);
+ if (gridMap.has("website")) grid->setWebSite(gridMap["website"]);
+ if (gridMap.has("support")) grid->setSupportUrl(gridMap["support"]);
+ if (gridMap.has("register")) grid->setRegisterUrl(gridMap["register"]);
+ if (gridMap.has("password")) grid->setPasswordUrl(gridMap["password"]);
+ //if (gridMap.has("search")) grid->setSearchUrl(gridMap["search"]);
+ if (gridMap.has("render_compat")) grid->setRenderCompat(gridMap["render_compat"]);
+ if (gridMap.has("firstname")) grid->setFirstName(gridMap["firstname"]);
+ if (gridMap.has("lastname")) grid->setLastName(gridMap["lastname"]);
+ if (gridMap.has("avatarpassword")) grid->setAvatarPassword(gridMap["avatarpassword"]);
+ if (newGrid) addGrid(grid);
+ }
+ }
+}
+
+
+void HippoGridManager::saveFile()
+{
+ // save default grid to client settings
+ gSavedSettings.setString("DefaultGrid", mDefaultGrid);
+
+ // build LLSD
+ LLSD gridInfo;
+ gridInfo[0]["default_grids_version"] = mDefaultGridsVersion;
+
+ // add grids
+ S32 i = 1;
+ GridIterator it, end = mGridInfo.end();
+ for (it = mGridInfo.begin(); it != end; ++it, i++) {
+ HippoGridInfo *grid = it->second;
+ gridInfo[i]["gridnick"] = grid->getGridNick();
+ gridInfo[i]["platform"] = HippoGridInfo::getPlatformString(grid->getPlatform());
+ gridInfo[i]["gridname"] = grid->getGridName();
+ gridInfo[i]["loginuri"] = grid->getLoginUri();
+ gridInfo[i]["loginpage"] = grid->getLoginPage();
+ gridInfo[i]["helperuri"] = grid->getHelperUri();
+ gridInfo[i]["website"] = grid->getWebSite();
+ gridInfo[i]["support"] = grid->getSupportUrl();
+ gridInfo[i]["register"] = grid->getRegisterUrl();
+ gridInfo[i]["firstname"] = grid->getFirstName();
+ gridInfo[i]["lastname"] = grid->getLastName();
+ gridInfo[i]["avatarpassword"] = grid->getAvatarPassword();
+
+ //gridInfo[i]["search"] = grid->getSearchUrl();
+ gridInfo[i]["render_compat"] = grid->isRenderCompat();
+ }
+
+ // write client grid info file
+ std::string fileName = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "grid_info.xml");
+ llofstream file;
+ file.open(fileName.c_str());
+ if (file.is_open()) {
+ LLSDSerialize::toPrettyXML(gridInfo, file);
+ file.close();
+ llinfos << "Saved grids to " << fileName << llendl;
+ } else {
+ llerrs << "Unable to open grid info file: " << fileName << llendl;
+ }
+}
diff --git a/linden/indra/newview/hippoGridManager.h b/linden/indra/newview/hippoGridManager.h
new file mode 100644
index 0000000..933a944
--- /dev/null
+++ b/linden/indra/newview/hippoGridManager.h
@@ -0,0 +1,171 @@
+#ifndef __HIPPO_GRID_MANAGER_H__
+#define __HIPPO_GRID_MANAGER_H__
+
+
+#include
+#include
+
+#ifndef XML_STATIC
+#define XML_STATIC
+#endif
+#include
+
+
+class LLSD;
+
+
+class HippoGridInfo
+{
+public:
+ enum Platform {
+ PLATFORM_OTHER = 0,
+ PLATFORM_OPENSIM,
+ PLATFORM_SECONDLIFE,
+ PLATFORM_LAST
+ };
+ enum SearchType {
+ SEARCH_ALL_EMPTY,
+ SEARCH_ALL_QUERY,
+ SEARCH_ALL_TEMPLATE
+ };
+
+ explicit HippoGridInfo(const std::string &gridNick);
+
+ Platform getPlatform() const { return mPlatform; }
+ const std::string &getGridNick() const { return mGridNick; }
+ const std::string &getGridName() const { return mGridName; }
+ const std::string &getLoginUri() const { return mLoginUri; }
+ const std::string &getLoginPage() const { return mLoginPage; }
+ const std::string &getHelperUri() const { return mHelperUri; }
+ const std::string &getWebSite() const { return mWebSite; }
+ const std::string &getSupportUrl() const { return mSupportUrl; }
+ const std::string &getRegisterUrl() const { return mRegisterUrl; }
+ const std::string &getPasswordUrl() const { return mPasswordUrl; }
+ const std::string &getSearchUrl() const { return mSearchUrl; }
+ const std::string &getFirstName() const { return mFirstName; }
+ const std::string &getLastName() const { return mLastName; }
+ const std::string &getAvatarPassword() const { return mAvatarPassword; }
+ std::string getSearchUrl(SearchType ty) const;
+ bool isRenderCompat() const { return mRenderCompat; }
+
+ const std::string &getCurrencySymbol() const { return mCurrencySymbol; }
+ const std::string &getRealCurrencySymbol() const { return mRealCurrencySymbol; }
+ std::string getUploadFee() const;
+ std::string getGroupCreationFee() const;
+ std::string getDirectoryFee() const;
+
+ bool isOpenSimulator() const { return (mPlatform == PLATFORM_OPENSIM ); }
+ bool isSecondLife() const { return (mPlatform == PLATFORM_SECONDLIFE); }
+
+ void setPlatform (const std::string &platform);
+ void setPlatform (Platform platform);
+ void setGridName (const std::string &gridName) { mGridName = gridName; }
+ void setLoginUri (const std::string &loginUri) { mLoginUri = loginUri; cleanUpUri(mLoginUri); }
+ void setLoginPage(const std::string &loginPage) { mLoginPage = loginPage; }
+ void setHelperUri(const std::string &helperUri) { mHelperUri = helperUri; cleanUpUri(mHelperUri); }
+ void setWebSite (const std::string &website) { mWebSite = website; }
+ void setSupportUrl(const std::string &url) { mSupportUrl = url; }
+ void setRegisterUrl(const std::string &url) { mRegisterUrl = url; }
+ void setPasswordUrl(const std::string &url) { mPasswordUrl = url; }
+ void setSearchUrl(const std::string &url) { mSearchUrl = url; }
+ void setRenderCompat(bool compat) { mRenderCompat = compat; }
+ void setFirstName(const std::string &firstName) { mFirstName = firstName; } //aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ void setLastName(const std::string &lastName) { mLastName = lastName; }
+ void setAvatarPassword(const std::string &avatarPassword) { mAvatarPassword = avatarPassword; }
+
+ void setCurrencySymbol(const std::string &sym) { mCurrencySymbol = sym.substr(0, 3); }
+ void setRealCurrencySymbol(const std::string &sym) { mRealCurrencySymbol = sym.substr(0, 3); }
+ void setDirectoryFee(int fee) { mDirectoryFee = fee; }
+
+ bool retrieveGridInfo();
+
+ static const char *getPlatformString(Platform platform);
+ static void cleanUpGridNick(std::string &gridnick);
+
+ static HippoGridInfo FALLBACK_GRIDINFO;
+ static void initFallback();
+
+private:
+ Platform mPlatform;
+ std::string mGridNick;
+ std::string mGridName;
+ std::string mLoginUri;
+ std::string mLoginPage;
+ std::string mHelperUri;
+ std::string mWebSite;
+ std::string mSupportUrl;
+ std::string mRegisterUrl;
+ std::string mPasswordUrl;
+ std::string mSearchUrl;
+ std::string mFirstName;
+ std::string mLastName;
+ std::string mAvatarPassword;
+ bool mRenderCompat;
+
+ std::string mCurrencySymbol;
+ std::string mRealCurrencySymbol;
+ int mDirectoryFee;
+
+ // for parsing grid info XML
+ enum XmlState {
+ XML_VOID, XML_GRIDNICK, XML_PLATFORM, XML_GRIDNAME,
+ XML_LOGINURI, XML_LOGINPAGE, XML_HELPERURI,
+ XML_WEBSITE, XML_SUPPORT, XML_REGISTER, XML_PASSWORD, XML_SEARCH
+ };
+ XmlState mXmlState;
+
+ static void cleanUpUri(std::string &uri);
+ void formatFee(std::string &fee, int cost, bool showFree) const;
+
+ static void onXmlElementStart(void *userData, const XML_Char *name, const XML_Char **atts);
+ static void onXmlElementEnd(void *userData, const XML_Char *name);
+ static void onXmlCharacterData(void *userData, const XML_Char *s, int len);
+};
+
+
+class HippoGridManager
+{
+public:
+ HippoGridManager();
+ ~HippoGridManager();
+
+ void init();
+ void saveFile();
+ void discardAndReload();
+
+ HippoGridInfo *getGrid(const std::string &grid) const;
+ HippoGridInfo *getConnectedGrid() const { return (mConnectedGrid)? mConnectedGrid: getCurrentGrid(); }
+ HippoGridInfo *getCurrentGrid() const;
+ const std::string &getDefaultGridNick() const { return mDefaultGrid; }
+ const std::string &getCurrentGridNick() const { return mCurrentGrid; }
+
+ void setDefaultGrid(const std::string &grid);
+ void setCurrentGrid(const std::string &grid);
+ void setCurrentGridAsConnected() { mConnectedGrid = getCurrentGrid(); }
+
+ void addGrid(HippoGridInfo *grid);
+ void deleteGrid(const std::string &grid);
+
+ typedef std::map::iterator GridIterator;
+ GridIterator beginGrid() { return mGridInfo.begin(); }
+ GridIterator endGrid() { return mGridInfo.end(); }
+
+private:
+ std::map mGridInfo;
+ std::string mDefaultGrid;
+ std::string mCurrentGrid;
+ HippoGridInfo *mConnectedGrid;
+ int mDefaultGridsVersion;
+
+ void cleanup();
+ void loadFromFile();
+ void parseFile(const std::string &fileName, bool mergeIfNewer);
+ void parseUrl(const char *url, bool mergeIfNewer);
+ void parseData(LLSD &gridInfo, bool mergeIfNewer);
+};
+
+
+extern HippoGridManager *gHippoGridManager;
+
+
+#endif
diff --git a/linden/indra/newview/hippoLimits.cpp b/linden/indra/newview/hippoLimits.cpp
new file mode 100644
index 0000000..63a5899
--- /dev/null
+++ b/linden/indra/newview/hippoLimits.cpp
@@ -0,0 +1,54 @@
+
+
+#include "hippoLimits.h"
+
+#include "hippoGridManager.h"
+
+#include
+
+
+HippoLimits *gHippoLimits = 0;
+
+
+HippoLimits::HippoLimits()
+{
+ setLimits();
+}
+
+
+void HippoLimits::setLimits()
+{
+ if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) {
+ setSecondLifeLimits();
+ } else {
+ setOpenSimLimits();
+ }
+}
+
+
+void HippoLimits::setOpenSimLimits()
+{
+ mMaxAgentGroups = 100;
+ mMaxPrimScale = 256.0f;
+ mMaxHeight = 10000.0f;
+ if (gHippoGridManager->getConnectedGrid()->isRenderCompat()) {
+ llinfos << "Using rendering compatible OpenSim limits." << llendl;
+ mMinHoleSize = 0.05f;
+ mMaxHollow = 0.95f;
+ } else {
+ llinfos << "Using Hippo OpenSim limits." << llendl;
+ mMinHoleSize = 0.01f;
+ mMaxHollow = 0.99f;
+ }
+}
+
+void HippoLimits::setSecondLifeLimits()
+{
+ llinfos << "Using Second Life limits." << llendl;
+ mMaxAgentGroups = 25;
+ mMaxPrimScale = 10.0f;
+ mMaxHeight = 4096.0f;
+ mMinHoleSize = 0.05f;
+ mMaxHollow = 0.95f;
+}
+
diff --git a/linden/indra/newview/hippoLimits.h b/linden/indra/newview/hippoLimits.h
new file mode 100644
index 0000000..333a979
--- /dev/null
+++ b/linden/indra/newview/hippoLimits.h
@@ -0,0 +1,33 @@
+#ifndef __HIPPO_LIMITS_H__
+#define __HIPPO_LIMITS_H__
+
+
+class HippoLimits
+{
+public:
+ HippoLimits();
+
+ int getMaxAgentGroups() const { return mMaxAgentGroups; }
+ float getMaxHeight() const { return mMaxHeight; }
+ float getMinHoleSize() const { return mMinHoleSize; }
+ float getMaxHollow() const { return mMaxHollow; }
+ float getMaxPrimScale() const { return mMaxPrimScale; }
+
+ void setLimits();
+
+private:
+ int mMaxAgentGroups;
+ float mMaxHeight;
+ float mMinHoleSize;
+ float mMaxHollow;
+ float mMaxPrimScale;
+
+ void setOpenSimLimits();
+ void setSecondLifeLimits();
+};
+
+
+extern HippoLimits *gHippoLimits;
+
+
+#endif
diff --git a/linden/indra/newview/hippoRestRequest.cpp b/linden/indra/newview/hippoRestRequest.cpp
new file mode 100644
index 0000000..ab8a557
--- /dev/null
+++ b/linden/indra/newview/hippoRestRequest.cpp
@@ -0,0 +1,54 @@
+
+
+#include "hippoRestRequest.h"
+
+#ifndef CURL_STATICLIB
+#define CURL_STATICLIB 1
+#endif
+#include
+
+#include
+#include
+
+
+static size_t curlWrite(void *ptr, size_t size, size_t nmemb, void *userData)
+{
+ std::string *result = (std::string*)userData;
+ size_t bytes = (size * nmemb);
+ result->append((char*)ptr, bytes);
+ return nmemb;
+}
+
+
+//static
+int HippoRestRequest::getBlocking(const std::string &url, std::string *result)
+{
+ llinfos << "Requesting: " << url << llendl;
+
+ char curlErrorBuffer[CURL_ERROR_SIZE];
+ CURL* curlp = curl_easy_init();
+
+ curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts
+ curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5); // seconds
+
+ curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, curlWrite);
+ curl_easy_setopt(curlp, CURLOPT_WRITEDATA, result);
+ curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curlErrorBuffer);
+ curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1);
+
+ *result = "";
+ S32 curlSuccess = curl_easy_perform(curlp);
+ S32 httpStatus = 499;
+ curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &httpStatus);
+
+ if (curlSuccess != 0) {
+ llwarns << "CURL ERROR (HTTP Status " << httpStatus << "): " << curlErrorBuffer << llendl;
+ } else if (httpStatus != 200) {
+ llwarns << "HTTP Error " << httpStatus << ", but no Curl error." << llendl;
+ }
+
+ curl_easy_cleanup(curlp);
+ return httpStatus;
+}
+
diff --git a/linden/indra/newview/hippoRestRequest.h b/linden/indra/newview/hippoRestRequest.h
new file mode 100644
index 0000000..e43233c
--- /dev/null
+++ b/linden/indra/newview/hippoRestRequest.h
@@ -0,0 +1,16 @@
+#ifndef __HIPPO_REST_REQTUEST_H__
+#define __HIPPO_REST_REQTUEST_H__
+
+
+#include
+
+
+class HippoRestRequest
+{
+ public:
+ static int getBlocking(const std::string &url, std::string *result);
+
+};
+
+
+#endif
diff --git a/linden/indra/newview/hippoUpdate.cpp b/linden/indra/newview/hippoUpdate.cpp
new file mode 100644
index 0000000..7a33487
--- /dev/null
+++ b/linden/indra/newview/hippoUpdate.cpp
@@ -0,0 +1,92 @@
+
+#include "hippoUpdate.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include "llviewercontrol.h"
+#include "llviewernetwork.h"
+#include "llweb.h"
+#include
+
+
+std::string gHippoChannel;
+
+
+// static
+bool HippoUpdate::checkUpdate()
+{
+ llinfos << "Hippo Update Check..." << llendl;
+
+ // get channel name
+ gHippoChannel = gSavedSettings.getString("ChannelName");
+
+ // get mac address
+ char macAddress[18];
+ sprintf(macAddress, "%02x:%02x:%02x:%02x:%02x:%02x",
+ gMACAddress[0], gMACAddress[1], gMACAddress[2], gMACAddress[3], gMACAddress[4], gMACAddress[5]);
+
+ // build URL for update check
+ char url[1000];
+ snprintf(url, 1000,
+/* "http://update.mjm.game-host.org/os/viewer.php?"
+ "product=%s&channel=%s&"
+ "version_major=%d&version_minor=%d&version_patch=%d&version_base=%s&"
+ "platform=%s&mac=%s",
+ LL_PRODUCT, LL_CHANNEL_CSTR,
+ LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VERSION_BASE,
+ LL_PLATFORM*/"", macAddress);
+
+ // query update server
+ std::string escaped_url = LLWeb::escapeURL(url);
+ LLSD response = LLHTTPClient::blockingGet(escaped_url.c_str());
+
+ // check response, return on error
+ S32 status = response["status"].asInteger();
+ if ((status != 200) || !response["body"].isMap()) {
+ llinfos << "Hippo Update failed (" << status << "): "
+ << (response["body"].isString()? response["body"].asString(): "")
+ << llendl;
+ return true;
+ }
+
+ // get data from response
+ LLSD data = response["body"];
+ std::string webpage = (data.has("webpage") && data["webpage"].isString())? data["webpage"].asString(): "";
+ std::string message = (data.has("message") && data["message"].isString())? data["message"].asString(): "";
+ std::string yourVersion = (data.has("yourVersion") && data["yourVersion"].isString())? data["yourVersion"].asString(): "";
+ std::string curVersion = (data.has("curVersion") && data["curVersion"].isString())? data["curVersion"].asString(): "";
+ bool update = (data.has("update") && data["update"].isBoolean())? data["update"].asBoolean(): false;
+ bool mandatory = (data.has("mandatory") && data["mandatory"].isBoolean())? data["mandatory"].asBoolean(): false;
+
+ // log and return, if no update available
+ llinfos << "Your version is " << yourVersion << ", current version is " << curVersion << '.' << llendl;
+ if (!update) return true;
+ llinfos << "Update is " << (mandatory? "mandatory.": "optional.") << llendl;
+
+ // show update dialog
+ char msg[1000];
+ snprintf(msg, 1000,
+ "There is a new viewer version available.\n"
+ "\n"
+ "Your version: %s\n"
+ "Current version: %s\n"
+ "%s\n"
+ "Do you want to visit the web site?",
+ yourVersion.c_str(), curVersion.c_str(),
+ mandatory? "\nThis is a mandatory update.\n": "");
+ S32 button = OSMessageBox(msg, "Hippo OpenSim Viewer Update", OSMB_YESNO);
+ if (button == OSBTN_YES) {
+ llinfos << "Taking user to " << webpage << llendl;
+ LLWeb::loadURLExternal(webpage);
+ // exit the viewer
+ return false;
+ }
+
+ return !mandatory;
+}
diff --git a/linden/indra/newview/hippoUpdate.h b/linden/indra/newview/hippoUpdate.h
new file mode 100644
index 0000000..632b2ef
--- /dev/null
+++ b/linden/indra/newview/hippoUpdate.h
@@ -0,0 +1,12 @@
+#ifndef __HIPPO_UPDATE_H__
+#define __HIPPO_UPDATE_H__
+
+
+class HippoUpdate
+{
+ public:
+ static bool checkUpdate();
+};
+
+
+#endif
diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp
index 4d53c88..60faaf2 100644
--- a/linden/indra/newview/llappviewer.cpp
+++ b/linden/indra/newview/llappviewer.cpp
@@ -125,6 +125,7 @@
#include "llvectorperfoptions.h"
#include "llurlsimstring.h"
#include "llwatchdog.h"
+#include "llcallingcard.h"
// Included so that constants/settings might be initialized
// in save_settings_to_globals()
@@ -164,6 +165,10 @@
#include "llcommandlineparser.h"
+#include "hippoGridManager.h"
+#include "hippoLimits.h"
+#include "hippoUpdate.h"
+
// annoying detail to determine whether font prefs are over-ridden
#if LL_LINUX
# define LL_DYNAMIC_FONT_DISCOVERY 1
@@ -192,22 +197,35 @@
//----------------------------------------------------------------------------
// viewer.cpp - these are only used in viewer, should be easily moved.
+extern void disable_win_error_reporting();
#if LL_DARWIN
+#include
extern void init_apple_menu(const char* product);
+extern OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
+extern OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
+extern OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata);
+#include
#endif // LL_DARWIN
+
extern BOOL gRandomizeFramerate;
extern BOOL gPeriodicSlowFrame;
extern BOOL gDebugGL;
////////////////////////////////////////////////////////////
// All from the last globals push...
+
+
const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user flagged as Away From Keyboard
F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
F32 gSimFrames;
+std::string gDisabledMessage; // Set in LLAppViewer::initConfiguration used in idle_startup
+
+BOOL gHideLinks = FALSE; // Set in LLAppViewer::initConfiguration, used externally
+
BOOL gAllowIdleAFK = TRUE;
BOOL gAllowTapTapHoldRun = TRUE;
BOOL gShowObjectUpdates = FALSE;
@@ -233,7 +251,7 @@ F32 gFPSClamped = 10.f; // Pretend we start at target rate.
F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets
U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
U32 gFrameStalls = 0;
-const F64 FRAME_STALL_THRESHOLD = 1.0;
+const F64 FRAME_STALL_THRESHOLD = 5.0;
LLTimer gRenderStartTime;
LLFrameTimer gForegroundTime;
@@ -302,7 +320,8 @@ std::string gLoginPage;
std::vector gLoginURIs;
static std::string gHelperURI;
-LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
+//FIXME
+//LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
void idle_afk_check()
{
@@ -453,7 +472,7 @@ static void settings_modify()
gSavedSettings.setBOOL("VectorizeSkin", FALSE);
#endif
}
-
+/*
void LLAppViewer::initGridChoice()
{
// Load up the initial grid choice from:
@@ -470,7 +489,7 @@ void LLAppViewer::initGridChoice()
if(grid_choice.empty())
{
S32 server = gSavedSettings.getS32("ServerChoice");
- server = llclamp(server, 0, (S32)GRID_INFO_COUNT - 1);
+ //server = llclamp(server, 0, (S32)GRID_INFO_COUNT - 1);
if(server == GRID_INFO_OTHER)
{
std::string custom_server = gSavedSettings.getString("CustomServer");
@@ -478,11 +497,12 @@ void LLAppViewer::initGridChoice()
}
else if(server != (S32)GRID_INFO_NONE)
{
- LLViewerLogin::getInstance()->setGridChoice((EGridInfo)server);
+ llwarns << "setgridchoice = " << server << llendl;
+ LLViewerLogin::getInstance()->setGridChoice(server);
}
}
}
-
+*/
//virtual
bool LLAppViewer::initSLURLHandler()
{
@@ -521,6 +541,7 @@ LLAppViewer::LLAppViewer() :
mSecondInstance(false),
mSavedFinalSnapshot(false),
mQuitRequested(false),
+ mLogoutRequested(false),
mLogoutRequestSent(false),
mYieldTime(-1),
mMainloopTimeout(NULL),
@@ -662,7 +683,6 @@ bool LLAppViewer::init()
ui_audio_callback,
&LLUI::sGLScaleFactor);
LLWeb::initClass(); // do this after LLUI
-
LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
&LLURLDispatcher::dispatchFromTextEditor,
&LLURLDispatcher::dispatchFromTextEditor);
@@ -683,6 +703,7 @@ bool LLAppViewer::init()
// load MIME type -> media impl mappings
LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") );
+
// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
settings_to_globals();
// Setup settings listeners
@@ -1117,12 +1138,21 @@ bool LLAppViewer::cleanup()
// to ensure shutdown order
LLMortician::setZealous(TRUE);
+ if (mQuitRequested)
LLVoiceClient::terminate();
disconnectViewer();
llinfos << "Viewer disconnected" << llendflush;
+
+
+
+
+ //this deletes all your buddies
+ LLAvatarTracker::instance().reset();
+
+ if (mQuitRequested)
display_cleanup();
release_start_screen(); // just in case
@@ -1137,6 +1167,13 @@ bool LLAppViewer::cleanup()
LLKeyframeDataCache::clear();
+ //clear all the chat off the screen
+ gConsole->clear();
+
+ if (!mQuitRequested) //if we are doing a soft cleanup, bail here
+ {
+ return true;
+ }
// End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
#if 0 // this seems to get us stuck in an infinite loop...
gTransferManager.cleanup();
@@ -1242,6 +1279,9 @@ bool LLAppViewer::cleanup()
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
delete gKeyboard;
gKeyboard = NULL;
+ // Clean up selection managers after UI is destroyed, as UI
+ // may be observing them.
+ LLSelectMgr::cleanupGlobals();
LLViewerObject::cleanupVOClasses();
@@ -1251,6 +1291,7 @@ bool LLAppViewer::cleanup()
LLTracker::cleanupInstance();
+
// *FIX: This is handled in LLAppViewerWin32::cleanup().
// I'm keeping the comment to remember its order in cleanup,
// in case of unforseen dependency.
@@ -1319,6 +1360,7 @@ bool LLAppViewer::cleanup()
// save mute list. gMuteList used to also be deleted here too.
LLMuteList::getInstance()->cache(gAgent.getID());
+
if (mPurgeOnExit)
{
llinfos << "Purging all cache files on exit" << llendflush;
@@ -1819,7 +1861,14 @@ bool LLAppViewer::initConfiguration()
}
}
- initGridChoice();
+ //init Hippo grid manager
+ if (!gHippoGridManager) {
+ gHippoGridManager = new HippoGridManager();
+ gHippoGridManager->init();
+ }
+
+
+ //initGridChoice();
// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
if(clp.hasOption("crashonstartup"))
@@ -1836,7 +1885,6 @@ bool LLAppViewer::initConfiguration()
// achieve this. For now...
// *NOTE:Mani The command line parser parses tokens and is
- // setup to bail after parsing the '--url' option or the
// first option specified without a '--option' flag (or
// any other option that uses the 'last_option' setting -
// see LLControlGroupCLP::configure())
@@ -1894,6 +1942,22 @@ bool LLAppViewer::initConfiguration()
// llerrs << "Failed to parse skin definition." << llendl;
// }
+ // LLXmlTreeNode* rootp = skin_def_tree.getRoot();
+ // LLXmlTreeNode* disabled_message_node = rootp->getChildByName("disabled_message");
+ // if (disabled_message_node)
+ // {
+ // gDisabledMessage = disabled_message_node->getContents();
+ // }
+
+ // static LLStdStringHandle hide_links_string = LLXmlTree::addAttributeString("hide_links");
+ // rootp->getFastAttributeBOOL(hide_links_string, gHideLinks);
+
+ // // Legacy string. This flag really meant we didn't want to expose references to "Second Life".
+ // // Just set gHideLinks instead.
+ // static LLStdStringHandle silent_string = LLXmlTree::addAttributeString("silent_update");
+ // BOOL silent_update;
+ // rootp->getFastAttributeBOOL(silent_string, silent_update);
+ // gHideLinks = (gHideLinks || silent_update);
//}
#if LL_DARWIN
@@ -2315,7 +2379,7 @@ void LLAppViewer::handleViewerCrash()
gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
- gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
+//FIXME gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) getCurrentRSS() >> 10;
if(gLogoutInProgress)
@@ -2542,28 +2606,55 @@ void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
}
}
+
+//this gets called after we get a packet back from the
+//server saying we are logged out, or if the packet times
+//out
void LLAppViewer::forceQuit()
{
+
+ LL_INFOS("forceQuit") << "Destroying the entire world" << LL_ENDL;
+ if (mQuitRequested)
LLApp::setQuitting();
+ else
+ {
+ if (mLogoutRequested) //we just finished a logout request
+ {
+ //LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+ LLStartUp::resetLogin();
+ cleanup();
+ mLogoutRequested=false;
+ mLogoutRequestSent=false;
+ }
+ }
}
-void LLAppViewer::requestQuit()
+void LLAppViewer::requestLogout(bool quit_after)
{
- llinfos << "requestQuit" << llendl;
+
+ mLogoutRequested=true;
+ if(quit_after)
+ mQuitRequested=true;
+ else
+ mQuitRequested=false;
+
+ llinfos << "requestLogout" << llendl;
LLViewerRegion* region = gAgent.getRegion();
- if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
+ if( (LLStartUp::getStartupState() >= STATE_STARTED) && region )
{
- // Quit immediately
- forceQuit();
- return;
- }
-
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
effectp->setPositionGlobal(gAgent.getPositionGlobal());
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
LLHUDManager::getInstance()->sendEffects();
+ send_stats();
+ }
+ else
+ {
+ mQuitRequested=true;
+ LLAppViewer::instance()->forceQuit();
+ }
// Attempt to close all floaters that might be
// editing things.
@@ -2573,17 +2664,14 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
}
- send_stats();
-
gLogoutTimer.reset();
- mQuitRequested = true;
}
static void finish_quit(S32 option, void *userdata)
{
if (option == 0)
{
- LLAppViewer::instance()->requestQuit();
+ LLAppViewer::instance()->requestLogout(true);
}
}
@@ -2592,6 +2680,12 @@ void LLAppViewer::userQuit()
gViewerWindow->alertXml("ConfirmQuit", finish_quit, NULL);
}
+//static
+void LLAppViewer::userLogout(void *userdata)
+{
+ LLAppViewer::instance()->requestLogout(false);
+}
+
static void finish_early_exit(S32 option, void* userdata)
{
LLAppViewer::instance()->forceQuit();
@@ -2619,6 +2713,7 @@ void LLAppViewer::abortQuit()
{
llinfos << "abortQuit()" << llendl;
mQuitRequested = false;
+ mLogoutRequested = false;
}
bool LLAppViewer::initCache()
@@ -2895,7 +2990,7 @@ void finish_forced_disconnect(S32 /* option */, void* /* userdata */)
void LLAppViewer::forceDisconnect(const std::string& mesg)
{
- if (gDoDisconnect)
+ if (gDoDisconnect||mQuitRequested||mLogoutRequested)
{
// Already popped up one of these dialogs, don't
// do this again.
@@ -3198,9 +3293,12 @@ void LLAppViewer::idle()
// Check for away from keyboard, kick idle agents.
idle_afk_check();
+ if (!gDisconnected) //check again
+ {
// Update statistics for this frame
update_statistics(gFrameCount);
}
+ }
////////////////////////////////////////
//
@@ -3401,7 +3499,7 @@ void LLAppViewer::idle()
// Handle shutdown process, for example,
// wait for floaters to close, send quit message,
// forcibly quit if it has taken too long
- if (mQuitRequested)
+ if (mQuitRequested || mLogoutRequested)
{
idleShutdown();
}
@@ -3501,12 +3599,12 @@ void LLAppViewer::sendLogoutRequest()
if (mLogoutMarkerFile)
{
llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl;
- apr_file_close(mLogoutMarkerFile);
}
else
{
llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl;
}
+ apr_file_close(mLogoutMarkerFile);
}
}
@@ -3523,6 +3621,9 @@ static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
void LLAppViewer::idleNetwork()
{
+ if (gDisconnected)
+ return;
+
pingMainloopTimeout("idleNetwork");
gObjectList.mNumNewObjects = 0;
@@ -3609,7 +3710,11 @@ void LLAppViewer::idleNetwork()
gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
+ if (gDisconnected)
+ return;
+
// Retransmit unacknowledged packets.
+ if (gXferManager)
gXferManager->retransmitUnackedPackets();
gAssetStorage->checkForTimeouts();
@@ -3619,7 +3724,7 @@ void LLAppViewer::idleNetwork()
// Check that the circuit between the viewer and the agent's current
// region is still alive
LLViewerRegion *agent_region = gAgent.getRegion();
- if (agent_region)
+ if ((agent_region)&&(LLStartUp::getStartupState() == STATE_STARTED))
{
LLUUID this_region_id = agent_region->getRegionID();
bool this_region_alive = agent_region->isAlive();
@@ -3639,6 +3744,9 @@ void LLAppViewer::disconnectViewer()
{
return;
}
+
+ //set this true now, to prevent things from trying to access the network we are destroying
+ gDisconnected = TRUE;
//
// Cleanup after quitting.
//
@@ -3688,8 +3796,8 @@ void LLAppViewer::disconnectViewer()
// Now we just ask the LLWorld singleton to cleanly shut down.
LLWorld::getInstance()->destroyClass();
+ if (mQuitRequested)
cleanup_xfer_manager();
- gDisconnected = TRUE;
}
void LLAppViewer::forceErrorLLError()
diff --git a/linden/indra/newview/llappviewer.h b/linden/indra/newview/llappviewer.h
index 3be5de7..8d8e30f 100644
--- a/linden/indra/newview/llappviewer.h
+++ b/linden/indra/newview/llappviewer.h
@@ -61,13 +61,15 @@ public:
// Application control
void forceQuit(); // Puts the viewer into 'shutting down without error' mode.
- void requestQuit(); // Request a quit. A kinder, gentler quit.
+ void requestLogout(bool quit_after); // Request a logout, optionally quitting after
void userQuit(); // The users asks to quit. Confirm, then requestQuit()
+ static void userLogout(void *userdata); //graceful logout without quit
void earlyExit(const std::string& msg); // Display an error dialog and forcibly quit.
void forceExit(S32 arg); // exit() immediately (after some cleanup).
void abortQuit(); // Called to abort a quit request.
bool quitRequested() { return mQuitRequested; }
+ bool logoutRequested() { return mLogoutRequested; }
bool logoutRequestSent() { return mLogoutRequestSent; }
void writeDebugInfo();
@@ -157,11 +159,12 @@ protected:
virtual std::string generateSerialNumber() = 0; // Platforms specific classes generate this.
+
private:
bool initThreads(); // Initialize viewer threads, return false on failure.
bool initConfiguration(); // Initialize settings from the command line/config file.
- void initGridChoice();
+ //void initGridChoice();
bool initCache(); // Initialize local client cache.
void purgeCache(); // Clear the local cache.
@@ -211,6 +214,7 @@ private:
bool mSavedFinalSnapshot;
bool mQuitRequested; // User wants to quit, may have modified documents open.
+ bool mLogoutRequested; // User wants to log out, but not quit
bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim.
S32 mYieldTime;
LLSD mSettingsFileList;
@@ -220,15 +224,6 @@ private:
// for tracking viewer<->region circuit death
bool mAgentRegionLastAlive;
LLUUID mAgentRegionLastID;
-
-public:
- //some information for updater
- typedef struct
- {
- std::string mUpdateExePath;
- std::ostringstream mParams;
- }LLUpdaterInfo ;
- static LLUpdaterInfo *sUpdaterInfo ;
};
// consts from viewer.h
@@ -239,6 +234,9 @@ const S32 AGENT_UPDATES_PER_SECOND = 10;
//
// "// llstartup" indicates that llstartup is the only client for this global.
+
+extern std::string gDisabledMessage; // llstartup
+extern BOOL gHideLinks; // used by llpanellogin, lllfloaterbuycurrency, llstartup
extern LLSD gDebugInfo;
extern BOOL gAllowIdleAFK;
diff --git a/linden/indra/newview/llappviewerlinux.h b/linden/indra/newview/llappviewerlinux.h
index b464e48..2f5c13b 100644
--- a/linden/indra/newview/llappviewerlinux.h
+++ b/linden/indra/newview/llappviewerlinux.h
@@ -61,9 +61,10 @@ public:
protected:
virtual bool beingDebugged();
-
+
virtual bool restoreErrorTrap();
virtual void handleCrashReporting(bool reportFreeze);
+
virtual void handleSyncCrashTrace();
virtual bool initLogging();
diff --git a/linden/indra/newview/llcallingcard.cpp b/linden/indra/newview/llcallingcard.cpp
index 1d353fa..ccecef9 100644
--- a/linden/indra/newview/llcallingcard.cpp
+++ b/linden/indra/newview/llcallingcard.cpp
@@ -136,8 +136,20 @@ LLAvatarTracker::~LLAvatarTracker()
deleteTrackingData();
std::for_each(mObservers.begin(), mObservers.end(), DeletePointer());
std::for_each(mBuddyInfo.begin(), mBuddyInfo.end(), DeletePairedPointer());
+ mObservers.erase(mObservers.begin(), mObservers.end());
+ mBuddyInfo.erase(mBuddyInfo.begin(), mBuddyInfo.end());
}
+
+void LLAvatarTracker::reset()
+{
+ std::for_each(mBuddyInfo.begin(), mBuddyInfo.end(), DeletePairedPointer());
+ mBuddyInfo.erase(mBuddyInfo.begin(), mBuddyInfo.end());
+ mModifyMask |= LLFriendObserver::REMOVE;
+ notifyObservers();
+}
+
+
void LLAvatarTracker::track(const LLUUID& avatar_id, const std::string& name)
{
deleteTrackingData();
diff --git a/linden/indra/newview/llcallingcard.h b/linden/indra/newview/llcallingcard.h
index cbcb237..21eea2b 100644
--- a/linden/indra/newview/llcallingcard.h
+++ b/linden/indra/newview/llcallingcard.h
@@ -85,7 +85,7 @@ class LLAvatarTracker
{
public:
static LLAvatarTracker& instance() { return sInstance; }
-
+ void reset();
void track(const LLUUID& avatar_id, const std::string& name);
void untrack(const LLUUID& avatar_id);
bool isTrackedAgentValid() { return mTrackedAgentValid; }
diff --git a/linden/indra/newview/lldrawable.h b/linden/indra/newview/lldrawable.h
index 15ad2e1..8f18be0 100644
--- a/linden/indra/newview/lldrawable.h
+++ b/linden/indra/newview/lldrawable.h
@@ -49,6 +49,7 @@
#include "llviewerobject.h"
#include "llrect.h"
#include "llappviewer.h" // for gFrameTimeSeconds
+#include "llimagej2c.h"
class LLCamera;
class LLDrawPool;
diff --git a/linden/indra/newview/llfloaterworldmap.cpp b/linden/indra/newview/llfloaterworldmap.cpp
index bc61d8a..b235265 100644
--- a/linden/indra/newview/llfloaterworldmap.cpp
+++ b/linden/indra/newview/llfloaterworldmap.cpp
@@ -68,6 +68,12 @@
#include "llappviewer.h"
#include "llmapimagetype.h"
#include "llweb.h"
+#include "floaterlogin.h"
+#include "llstartup.h"
+#include "hippoGridManager.h"
+#include "floaterlogin.h"
+#include "llpanellogin.h"
+
#include "llglheaders.h"
@@ -237,6 +243,10 @@ BOOL LLFloaterWorldMap::postBuild()
landmark_combo->setTextEntryCallback( onComboTextEntry );
}
+ childSetCommitCallback("grid_combo", onSelectServer, this);
+
+ childSetAction("Grid Manager", onGridManager, this);
+
childSetAction("Go Home", onGoHome, this);
childSetAction("Teleport", onClickTeleportBtn, this);
@@ -327,6 +337,8 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target)
// If nothing is being tracked, set flag so the user position will be found
gFloaterWorldMap->mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
+
+ LLFloaterWorldMap::addServer(gHippoGridManager->getDefaultGridNick());
}
if (center_on_target)
@@ -371,6 +383,48 @@ void LLFloaterWorldMap::hide(void*)
}
+// static
+void LLFloaterWorldMap::addServer(const std::string& server)
+{
+ const std::string &defaultGrid = gHippoGridManager->getDefaultGridNick();
+
+ LLCtrlListInterface *grids = gFloaterWorldMap->childGetListInterface("grid_combo");
+ if (!grids) return;
+
+ // Delete all but the "None" entry
+ S32 list_size = grids->getItemCount();
+ while (list_size > 1)
+ {
+ grids->selectNthItem(1);
+ grids->operateOnSelection(LLCtrlListInterface::OP_DELETE);
+ --list_size;
+ }
+
+
+ //LLComboBox *grids = gFloaterWorldMap->getChild("grid_combo");
+ S32 selectIndex = -1, i = 0;
+ //grids->removeall();
+ if (defaultGrid != "") {
+ grids->addSimpleElement(defaultGrid);
+ selectIndex = i++;
+ }
+ HippoGridManager::GridIterator it, end = gHippoGridManager->endGrid();
+ for (it = gHippoGridManager->beginGrid(); it != end; ++it) {
+ const std::string &grid = it->second->getGridNick();
+ if (grid != defaultGrid) {
+ grids->addSimpleElement(grid);
+ //if (grid == mCurGrid) selectIndex = i;
+ i++;
+ }
+ }
+ grids->selectFirstItem();
+ //grids->setCurrentByIndex(0);
+
+ //LLComboBox* combo = sInstance->getChild("server_combo");
+ //combo->add(server, LLSD(domain_name) );
+ //combo->setCurrentByIndex(0);
+}
+
// virtual
void LLFloaterWorldMap::setVisible( BOOL visible )
{
@@ -443,7 +497,10 @@ void LLFloaterWorldMap::draw()
childSetEnabled("Go Home", enable_go_home);
updateLocation();
-
+
+ LLComboBox *grid_combo = getChild("grid_combo");
+ std::string current_grid = gHippoGridManager->getConnectedGrid()->getGridNick();
+
LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
if (LLTracker::TRACKING_AVATAR == tracking_status)
{
@@ -489,7 +546,19 @@ void LLFloaterWorldMap::draw()
centerOnTarget(TRUE);
}
- childSetEnabled("Teleport", (BOOL)tracking_status);
+ //GRID MANAGER
+ if (grid_combo->getSelectedValue().asString() != "None")
+ {
+ childSetEnabled("Teleport", TRUE);
+ childSetColor("grid_icon", gTrackColor);
+ }
+ else
+ {
+ childSetEnabled("Teleport", (BOOL)tracking_status);
+ childSetColor("grid_icon", gDisabledTrackColor);
+ }
+ //END GRID MANAGER
+
// childSetEnabled("Clear", (BOOL)tracking_status);
childSetEnabled("Show Destination", (BOOL)tracking_status || LLWorldMap::getInstance()->mIsTrackingUnknownLocation);
childSetEnabled("copy_slurl", (mSLURL.size() > 0) );
@@ -743,7 +812,7 @@ void LLFloaterWorldMap::updateLocation()
void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S32 y_coord, S32 z_coord)
{
LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromName(region_name);
- z_coord = llclamp(z_coord, 0, 4096);
+ z_coord = llclamp(z_coord, 0, 1000);
if (sim_info)
{
LLVector3 local_pos;
@@ -953,6 +1022,18 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
}
+void LLFloaterWorldMap::clearGridSelection(BOOL clear_ui)
+{
+ if (clear_ui || !childHasKeyboardFocus("grid_combo"))
+ {
+ LLCtrlListInterface *list = childGetListInterface("grid_combo");
+ if (list)
+ {
+ list->selectByValue( "None" );
+ }
+ }
+}
+
void LLFloaterWorldMap::clearLandmarkSelection(BOOL clear_ui)
{
if (clear_ui || !childHasKeyboardFocus("landmark combo"))
@@ -1050,9 +1131,18 @@ void LLFloaterWorldMap::onPanBtn( void* userdata )
}
// static
+void LLFloaterWorldMap::onGridManager(void*)
+{
+ LoginFloater::newShow(std::string("Test"), false, LoginFloater::testCallback, NULL);
+ //gAgent.teleportHome();
+ //gFloaterWorldMap->close();
+}
+
+// static
void LLFloaterWorldMap::onGoHome(void*)
{
gAgent.teleportHomeConfirm();
+ gFloaterWorldMap->close();
}
@@ -1135,6 +1225,9 @@ void LLFloaterWorldMap::onLandmarkComboCommit( LLUICtrl* ctrl, void* userdata )
item_id.setNull();
}
}
+ //GRID MANAGER HAX
+ self->clearGridSelection(TRUE);
+ //END GRID MANAGER HAX
self->trackLandmark( item_id);
onShowTargetBtn(self);
@@ -1186,6 +1279,10 @@ void LLFloaterWorldMap::onAvatarComboCommit( LLUICtrl* ctrl, void* userdata )
const LLUUID& new_avatar_id = list->getCurrentID();
if (new_avatar_id.notNull())
{
+ //GRID MANAGER HAX
+ self->clearGridSelection(TRUE);
+ //END GRID MANAGER HAX
+
std::string name;
LLComboBox* combo = gFloaterWorldMap->getChild("friend combo");
if (combo) name = combo->getSimple();
@@ -1267,6 +1364,10 @@ void LLFloaterWorldMap::onClearBtn(void* data)
LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
self->mSLURL = ""; // Clear the SLURL since it's invalid
self->mSetToUserPosition = TRUE; // Revert back to the current user position
+ //KOW TODO clear grid combo red ring, clear grid combo.
+ //GRID MANAGER HAX
+ self->clearGridSelection(TRUE);
+ //END GRID MANAGER HAX
}
// static
@@ -1376,6 +1477,39 @@ void LLFloaterWorldMap::fly()
// protected
void LLFloaterWorldMap::teleport()
{
+ //BEGIN CROSS GRIP TP//
+ LLComboBox *grid_combo = getChild("grid_combo");
+ std::string current_grid = gHippoGridManager->getConnectedGrid()->getGridNick();
+
+ // BUG: the client crashes if fed an invalid grid through this interface, which shouldn't happen
+ if(//grid_combo && grid_combo->getSelectedValue().asString() != current_grid || gSavedSettings.getBOOL("CmdLineLoginURI") &&
+ grid_combo->getSelectedValue().asString() != "None" &&
+ !grid_combo->getSelectedValue().asString().empty())
+ {
+ HippoGridInfo *gridInfo = gHippoGridManager->getGrid(grid_combo->getSelectedValue().asString());
+ //DEBUG
+
+ llwarns << "tp button current grid = " << grid_combo->getSelectedValue().asString() << llendl;
+ std::string firstName = gridInfo->getFirstName();
+ std::string lastName = gridInfo->getLastName();
+ std::string loginPassword = gridInfo->getAvatarPassword();
+
+ if(!firstName.empty() && !lastName.empty())
+ {
+ gLoginHandler.mFirstName = firstName;
+ gLoginHandler.mLastName = lastName;
+ gLoginHandler.mPassword = loginPassword;
+ }
+
+ gHippoGridManager->setCurrentGrid(gridInfo->getGridNick());
+ gHippoGridManager->setDefaultGrid(gridInfo->getGridNick());
+ //this doesn't work :( gSavedSettings.setBOOL("CmdLineLoginURI", FALSE);
+ LLStartUp::setShouldAutoLogin(true);
+ LLAppViewer::instance()->requestLogout(false);
+ return;
+ }
+ //END CROSS GRID TP//
+
BOOL teleport_home = FALSE;
LLVector3d pos_global;
LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
@@ -1666,3 +1800,20 @@ void LLFloaterWorldMap::onCommitSearchResult(LLUICtrl*, void* userdata)
onShowTargetBtn(self);
}
+
+// static
+void LLFloaterWorldMap::onSelectServer(LLUICtrl* ctrl, void* userdata)
+{
+ //GRID MANAGER COMBO BOX CLICKED//
+ llwarns << "onSelectServer called" << llendl;
+ //snip from onClearBtn (bless this mess)
+ LLFloaterWorldMap* self = (LLFloaterWorldMap*) userdata;
+ self->mTrackedStatus = LLTracker::TRACKING_NOTHING;
+ LLTracker::stopTracking((void *)(intptr_t)TRUE);
+ //LLTracker::stopTracking(NULL);
+ LLWorldMap::getInstance()->mIsTrackingUnknownLocation = FALSE;
+ self->mSLURL = ""; // Clear the SLURL since it's invalid
+ self->mSetToUserPosition = TRUE; // Revert back to the current user position
+
+ self->setDefaultBtn("Teleport");
+}
diff --git a/linden/indra/newview/llfloaterworldmap.h b/linden/indra/newview/llfloaterworldmap.h
index 568d3cc..2f444b9 100644
--- a/linden/indra/newview/llfloaterworldmap.h
+++ b/linden/indra/newview/llfloaterworldmap.h
@@ -67,6 +67,8 @@ public:
static void toggle(void*);
static void hide(void*);
+ static void addServer(const std::string& server);
+
/*virtual*/ void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE );
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
@@ -100,6 +102,7 @@ public:
void clearLocationSelection(BOOL clear_ui = FALSE);
void clearAvatarSelection(BOOL clear_ui = FALSE);
void clearLandmarkSelection(BOOL clear_ui = FALSE);
+ void clearGridSelection(BOOL clear_ui = FALSE);
// Adjust the maximally zoomed out limit of the zoom slider so you can
// see the whole world, plus a little.
@@ -114,8 +117,9 @@ public:
protected:
static void onPanBtn( void* userdata );
- static void onGoHome(void* data);
+ static void onGridManager(void* data);
+ static void onGoHome(void* data);
static void onLandmarkComboPrearrange( LLUICtrl* ctrl, void* data );
static void onLandmarkComboCommit( LLUICtrl* ctrl, void* data );
@@ -157,6 +161,7 @@ protected:
static void onLocationCommit( void* userdata );
static void onCommitLocation( LLUICtrl* ctrl, void* userdata );
static void onCommitSearchResult( LLUICtrl* ctrl, void* userdata );
+ static void onSelectServer(LLUICtrl*, void* userdata);
void cacheLandmarkPosition();
diff --git a/linden/indra/newview/llpanellogin.cpp b/linden/indra/newview/llpanellogin.cpp
index c26f70f..873920c 100644
--- a/linden/indra/newview/llpanellogin.cpp
+++ b/linden/indra/newview/llpanellogin.cpp
@@ -34,6 +34,8 @@
#include "llpanellogin.h"
#include "llpanelgeneral.h"
+#include "hippoGridManager.h"
+
#include "indra_constants.h" // for key and mask constants
#include "llfontgl.h"
#include "llmd5.h"
@@ -63,17 +65,22 @@
#include "llviewernetwork.h"
#include "llviewerwindow.h" // to link into child list
#include "llnotify.h"
+#include "llappviewer.h" // for gHideLinks
#include "llurlsimstring.h"
#include "lluictrlfactory.h"
#include "llhttpclient.h"
#include "llweb.h"
#include "llwebbrowserctrl.h"
+#include "llfloaterhtml.h"
+
#include "llfloaterhtmlhelp.h"
#include "llfloatertos.h"
#include "llglheaders.h"
+#include "floaterlogin.h"
+
#define USE_VIEWER_AUTH 0
std::string load_password_from_disk(void);
@@ -130,21 +137,8 @@ void LLLoginHandler::parse(const LLSD& queryMap)
mFirstName = queryMap["first_name"].asString();
mLastName = queryMap["last_name"].asString();
- EGridInfo grid_choice = GRID_INFO_NONE;
- if (queryMap["grid"].asString() == "sl beta grid")
- {
- grid_choice = GRID_INFO_ADITI;
- }
- else if (queryMap["grid"].asString() == "sl main grid")
- {
- grid_choice = GRID_INFO_AGNI;
- }
-
- if(grid_choice != GRID_INFO_NONE)
- {
- LLViewerLogin::getInstance()->setGridChoice(grid_choice);
- }
-
+ const std::string &grid = queryMap["grid"].asString();
+ if (grid != "") gHippoGridManager->setCurrentGrid(grid);
std::string startLocation = queryMap["location"].asString();
if (startLocation == "specify")
@@ -258,11 +252,6 @@ namespace {
boost::intrusive_ptr< LLIamHereLogin > gResponsePtr = 0;
};
-void set_start_location(LLUICtrl* ctrl, void* data)
-{
- LLURLSimString::setString(ctrl->getValue().asString());
-}
-
//---------------------------------------------------------------------------
// Public methods
//---------------------------------------------------------------------------
@@ -349,13 +338,13 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
combo->setCurrentByIndex( 0 );
}
- combo->setCommitCallback( &set_start_location );
LLComboBox* server_choice_combo = sInstance->getChild("server_combo");
server_choice_combo->setCommitCallback(onSelectServer);
- server_choice_combo->setFocusLostCallback(onServerComboLostFocus);
+ //server_choice_combo->setFocusLostCallback(onServerComboLostFocus);
childSetAction("connect_btn", onClickConnect, this);
+ childSetAction("grid_btn", onClickGrid, this);
setDefaultBtn("connect_btn");
@@ -657,6 +646,7 @@ void LLPanelLogin::show(const LLRect &rect,
// Make sure that focus always goes here (and use the latest sInstance that was just created)
gFocusMgr.setDefaultKeyboardFocus(sInstance);
+ LLPanelLogin::addServer(LLViewerLogin::getInstance()->getGridLabel());
}
// static
@@ -701,7 +691,7 @@ void LLPanelLogin::setFields(const std::string& firstname, const std::string& la
// static
-void LLPanelLogin::addServer(const std::string& server, S32 domain_name)
+void LLPanelLogin::addServer(const std::string& server)
{
if (!sInstance)
{
@@ -709,17 +699,29 @@ void LLPanelLogin::addServer(const std::string& server, S32 domain_name)
return;
}
- LLComboBox* combo = sInstance->getChild("server_combo");
- combo->add(server, LLSD(domain_name) );
- combo->setCurrentByIndex(0);
-}
+ const std::string &defaultGrid = gHippoGridManager->getDefaultGridNick();
+ LLComboBox *grids = sInstance->getChild("server_combo");
+ S32 selectIndex = -1, i = 0;
+ grids->removeall();
+ if (defaultGrid != "") {
+ grids->add(defaultGrid);
+ selectIndex = i++;
+ }
+ HippoGridManager::GridIterator it, end = gHippoGridManager->endGrid();
+ for (it = gHippoGridManager->beginGrid(); it != end; ++it) {
+ const std::string &grid = it->second->getGridNick();
+ if (grid != defaultGrid) {
+ grids->add(grid);
+ //if (grid == mCurGrid) selectIndex = i;
+ i++;
+ }
+ }
+ grids->setCurrentByIndex(0);
-// static
-void LLPanelLogin::setServer(S32 domain_name)
-{
- LLComboBox* combo = sInstance->getChild("server_combo");
- combo->setCurrentByIndex(domain_name);
+ //LLComboBox* combo = sInstance->getChild("server_combo");
+ //combo->add(server, LLSD(domain_name) );
+ //combo->setCurrentByIndex(0);
}
// static
@@ -800,7 +802,12 @@ void LLPanelLogin::refreshLocation( bool force_visible )
sInstance->childSetVisible("start_location_combo", show_start);
sInstance->childSetVisible("start_location_text", show_start);
+/*#if LL_RELEASE_FOR_DOWNLOAD
+ BOOL show_server = gSavedSettings.getBOOL("ForceShowGrid");
+ sInstance->childSetVisible("server_combo", show_server);
+#else*/
sInstance->childSetVisible("server_combo", TRUE);
+//#endif
#endif
}
@@ -833,18 +840,39 @@ void LLPanelLogin::setAlwaysRefresh(bool refresh)
}
+// static
+void LLPanelLogin::refreshLoginPage()
+{
+ if (!sInstance) return;
+
+ sInstance->childSetVisible("create_new_account_text",
+ !gHippoGridManager->getConnectedGrid()->getRegisterUrl().empty());
+ sInstance->childSetVisible("forgot_password_text",
+ !gHippoGridManager->getConnectedGrid()->getPasswordUrl().empty());
+
+ // kick off a request to grab the url manually
+ gResponsePtr = LLIamHereLogin::build(sInstance);
+ std::string login_page = gHippoGridManager->getConnectedGrid()->getLoginPage();
+ if (!login_page.empty()) {
+ LLHTTPClient::head(login_page, gResponsePtr);
+ } else {
+ sInstance->setSiteIsAlive(false);
+ }
+}
+
void LLPanelLogin::loadLoginPage()
{
if (!sInstance) return;
- std::ostringstream oStr;
- std::string login_page = gSavedSettings.getString("LoginPage");
- if (login_page.empty())
- {
- login_page = sInstance->getString( "real_url" );
+ std::string login_page = gHippoGridManager->getConnectedGrid()->getLoginPage();
+ if (login_page.empty()) {
+ sInstance->setSiteIsAlive(false);
+ return;
}
+
+ std::ostringstream oStr;
oStr << login_page;
// Use the right delimeter depending on how LLURI parses the URL
@@ -879,11 +907,12 @@ void LLPanelLogin::loadLoginPage()
curl_free(curl_version);
// Grid
- char* curl_grid = curl_escape(LLViewerLogin::getInstance()->getGridCodeName().c_str(), 0);
+ char* curl_grid = curl_escape(LLViewerLogin::getInstance()->getGridLabel().c_str(), 0);
oStr << "&grid=" << curl_grid;
curl_free(curl_grid);
gViewerWindow->setMenuBackgroundColor(false, !LLViewerLogin::getInstance()->isInProductionGrid());
+ //LLViewerLogin::getInstance()->setMenuColor();
gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
@@ -1017,12 +1046,27 @@ void LLPanelLogin::onClickConnect(void *)
}
else
{
+ if (gHideLinks)
+ {
+ gViewerWindow->alertXml("MustHaveAccountToLogInNoLinks");
+ }
+ else
+ {
gViewerWindow->alertXml("MustHaveAccountToLogIn",
LLPanelLogin::newAccountAlertCallback);
}
}
}
+}
+void LLPanelLogin::onClickGrid(void *)
+{
+ if (sInstance && sInstance->mCallback)
+ {
+ LoginFloater::newShow(std::string("Test"), false, LoginFloater::testCallback, NULL);
+ }
+}
+
// static
void LLPanelLogin::newAccountAlertCallback(S32 option, void*)
@@ -1088,7 +1132,7 @@ void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
}
// static
-void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
+void LLPanelLogin::onSelectServer(LLUICtrl* ctrl, void*)
{
// *NOTE: The paramters for this method are ignored.
// LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
@@ -1097,11 +1141,31 @@ void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
// The user twiddled with the grid choice ui.
// apply the selection to the grid setting.
std::string grid_label;
- S32 grid_index;
+ //S32 grid_index;
LLComboBox* combo = sInstance->getChild("server_combo");
LLSD combo_val = combo->getValue();
+ std::string mCurGrid = ctrl->getValue().asString();
+ //KOW
+ gHippoGridManager->setCurrentGrid(mCurGrid);
+ //gHippoGridManager->setDefaultGrid(mCurGrid);
+ //gHippoGridManager->saveFile();
+ HippoGridInfo *gridInfo = gHippoGridManager->getGrid(mCurGrid);
+ if (gridInfo) {
+ //childSetText("gridnick", gridInfo->getGridNick());
+ //platform->setCurrentByIndex(gridInfo->getPlatform());
+ //childSetText("gridname", gridInfo->getGridName());
+ LLPanelLogin::setFields( gridInfo->getFirstName(), gridInfo->getLastName(), gridInfo->getAvatarPassword(), 1 );
+ }
+ //gHippoGridManager->setCurrentGrid(mCurGrid);
+
+
+
+ llwarns << "current grid = " << mCurGrid << llendl;
+
+ /*
+
if (LLSD::TypeInteger == combo_val.type())
{
grid_index = combo->getValue().asInteger();
@@ -1126,17 +1190,27 @@ void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
vl->resetURIs();
if(grid_index != GRID_INFO_OTHER)
{
- vl->setGridChoice((EGridInfo)grid_index);
+ vl->setGridChoice(grid_index);
}
else
{
vl->setGridChoice(grid_label);
}
+ // clear the password if we are switching grids so we don't send
+ // the wrong pass to the wrong grid.
+ if (sInstance)
+ {
+ // no method to clear a text box?
+ const std::string nothing("");
+ sInstance->childSetText("password_edit", nothing);
+ }
+ */
// grid changed so show new splash screen (possibly)
loadLoginPage();
}
+/*
void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
{
LLComboBox* combo = sInstance->getChild("server_combo");
@@ -1145,3 +1219,4 @@ void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
onSelectServer(combo, NULL);
}
}
+*/
diff --git a/linden/indra/newview/llpanellogin.h b/linden/indra/newview/llpanellogin.h
index a303e32..8a9747b 100644
--- a/linden/indra/newview/llpanellogin.h
+++ b/linden/indra/newview/llpanellogin.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
- * Copyright (c) 2002-2009, Linden Research, Inc.
+ * Copyright (c) 2002-2008, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -60,6 +60,7 @@ class LLLoginHandler : public LLCommandHandler
LLUUID mWebLoginKey;
std::string mFirstName;
std::string mLastName;
+ std::string mPassword;
};
extern LLLoginHandler gLoginHandler;
@@ -86,8 +87,7 @@ public:
static void setFields(const std::string& firstname, const std::string& lastname,
const std::string& password, BOOL remember);
- static void addServer(const std::string& server, S32 domain_name);
- static void setServer(S32 domain_name);
+ static void addServer(const std::string& server);
static void refreshLocation( bool force_visible );
static void getFields(std::string& firstname, std::string& lastname,
@@ -101,12 +101,14 @@ public:
void setSiteIsAlive( bool alive );
static void loadLoginPage();
+ static void refreshLoginPage();
static void giveFocus();
static void setAlwaysRefresh(bool refresh);
static void mungePassword(LLUICtrl* caller, void* user_data);
private:
static void onClickConnect(void*);
+ static void onClickGrid(void*);
static void onClickNewAccount(void*);
static void newAccountAlertCallback(S32 option, void*);
static void onClickQuit(void*);
diff --git a/linden/indra/newview/llprogressview.cpp b/linden/indra/newview/llprogressview.cpp
index a38aada..157dc6c 100644
--- a/linden/indra/newview/llprogressview.cpp
+++ b/linden/indra/newview/llprogressview.cpp
@@ -407,7 +407,7 @@ void LLProgressView::onCancelButtonClicked(void*)
{
if (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE)
{
- LLAppViewer::instance()->requestQuit();
+ LLAppViewer::instance()->requestLogout(true);
}
else
{
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
index aca3cac..8f9b728 100644
--- a/linden/indra/newview/llstartup.cpp
+++ b/linden/indra/newview/llstartup.cpp
@@ -29,7 +29,14 @@
* $/LicenseInfo$
*/
-#include "llviewerprecompiledheaders.h"
+// #include "llviewerprecompiledheaders.h"
+
+
+#if LL_WINDOWS
+ #define WIN32_LEAN_AND_MEAN
+ #include
+ #include
+#endif
#include "llstartup.h"
@@ -190,6 +197,8 @@
#include "lldxhardware.h"
#endif
+#include "hippoGridManager.h"
+#include "hippoLimits.h"
//
// exported globals
//
@@ -222,7 +231,8 @@ static std::string sInitialOutfitGender; // "male" or "female"
static bool gUseCircuitCallbackCalled = false;
EStartupState LLStartUp::gStartupState = STATE_FIRST;
-
+bool LLStartUp::mStartedOnce = false;
+bool LLStartUp::mShouldAutoLogin = false;
//
// local function declaration
@@ -248,7 +258,6 @@ void dialog_choose_gender_first_start();
void callback_choose_gender(S32 option, void* userdata);
void init_start_screen(S32 location_id);
void release_start_screen();
-void reset_login();
void apply_udp_blacklist(const std::string& csv);
void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group, void* data)
@@ -322,6 +331,7 @@ bool idle_startup()
static S32 timeout_count = 0;
static LLTimer login_time;
+ static LLFrameTimer wearables_timer;
// until this is encapsulated, this little hack for the
// auth/transform loop will do.
@@ -654,7 +664,7 @@ bool idle_startup()
show_connect_box = false;
}
- else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
+ else if((gSavedSettings.getLLSD("UserLoginInfo").size() == 3) && !LLStartUp::shouldAutoLogin())
{
LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
firstname = cmd_line_login[0].asString();
@@ -721,12 +731,19 @@ bool idle_startup()
if (STATE_LOGIN_SHOW == LLStartUp::getStartupState())
{
LL_DEBUGS("AppInit") << "Initializing Window" << LL_ENDL;
+ sAuthUris.clear();
+ sAuthUriNum = -1;
gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
// Push our window frontmost
gViewerWindow->getWindow()->show();
timeout_count = 0;
+
+ if(LLStartUp::shouldAutoLogin())
+ {
+ show_connect_box = false;
+ }
if (show_connect_box)
{
@@ -809,6 +826,18 @@ bool idle_startup()
lastname = gLoginHandler.mLastName;
web_login_key = gLoginHandler.mWebLoginKey;
}
+
+ if(!gLoginHandler.mPassword.empty())
+ {
+ firstname = gLoginHandler.mFirstName;
+ lastname = gLoginHandler.mLastName;
+ password = gLoginHandler.mPassword;
+
+ gLoginHandler.mFirstName = "";
+ gLoginHandler.mLastName = "";
+ gLoginHandler.mPassword = "";
+ LLStartUp::setShouldAutoLogin(false);
+ }
if (show_connect_box)
{
@@ -836,10 +865,11 @@ bool idle_startup()
}
gSavedSettings.setBOOL("RememberPassword", remember_password);
- LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL;
+ LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << " " << password << LL_ENDL;
gDebugInfo["LoginName"] = firstname + " " + lastname;
}
+ gHippoGridManager->setCurrentGridAsConnected();
// create necessary directories
// *FIX: these mkdir's should error check
gDirUtilp->setLindenUserDir(firstname, lastname);
@@ -1031,6 +1061,10 @@ bool idle_startup()
LLStringUtil::format_map_t args;
args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle();
auth_desc = LLTrans::getString("LoginInProgress", args);
+
+ //Since we are about to login, we don't want the client to attempt auto login
+ //again until the user does a grid2grid teleport.
+ LLStartUp::setShouldAutoLogin(false);
LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
}
@@ -1070,13 +1104,15 @@ bool idle_startup()
hashed_mac.hex_digest(hashed_mac_string);
// TODO if statement here to use web_login_key
+ if(web_login_key.isNull()){
sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1);
LLUserAuth::getInstance()->authenticate(
sAuthUris[sAuthUriNum],
auth_method,
firstname,
lastname,
- password, // web_login_key,
+ password,
+ //web_login_key,
start.str(),
gSkipOptionalUpdate,
gAcceptTOS,
@@ -1085,6 +1121,22 @@ bool idle_startup()
requested_options,
hashed_mac_string,
LLAppViewer::instance()->getSerialNumber());
+ } else {
+ LLUserAuth::getInstance()->authenticate(
+ sAuthUris[sAuthUriNum],
+ auth_method,
+ firstname,
+ lastname,
+ web_login_key,
+ start.str(),
+ gSkipOptionalUpdate,
+ gAcceptTOS,
+ gAcceptCriticalMessage,
+ gLastExecEvent,
+ requested_options,
+ hashed_mac_string,
+ LLAppViewer::instance()->getSerialNumber());
+ }
// reset globals
gAcceptTOS = FALSE;
@@ -1144,7 +1196,6 @@ bool idle_startup()
LL_DEBUGS("AppInit") << "STATE_LOGIN_PROCESS_RESPONSE" << LL_ENDL;
std::ostringstream emsg;
bool quit = false;
- bool update = false;
std::string login_response;
std::string reason_response;
std::string message_response;
@@ -1188,7 +1239,11 @@ bool idle_startup()
reason_response = LLUserAuth::getInstance()->getResponse("reason");
message_response = LLUserAuth::getInstance()->getResponse("message");
- if (!message_response.empty())
+ if (gHideLinks && reason_response == "disabled")
+ {
+ emsg << gDisabledMessage;
+ }
+ else if (!message_response.empty())
{
// XUI: fix translation for strings returned during login
// We need a generic table for translations
@@ -1246,7 +1301,16 @@ bool idle_startup()
if(reason_response == "update")
{
auth_message = LLUserAuth::getInstance()->getResponse("message");
- update = true;
+ if (show_connect_box)
+ {
+ update_app(TRUE, auth_message);
+ LLStartUp::setStartupState( STATE_UPDATE_CHECK );
+ return false;
+ }
+ else
+ {
+ quit = true;
+ }
}
if(reason_response == "optional")
{
@@ -1284,21 +1348,6 @@ bool idle_startup()
break;
}
- if (update || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
- {
- gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
- if (show_connect_box)
- {
- update_app(TRUE, auth_message);
- LLStartUp::setStartupState( STATE_UPDATE_CHECK );
- return false;
- }
- else
- {
- quit = true;
- }
- }
-
// Version update and we're not showing the dialog
if(quit)
{
@@ -1511,6 +1560,42 @@ bool idle_startup()
}
}
+ // Override grid info with anything sent in the login response
+ std::string tmp = LLUserAuth::getInstance()->getResponse("gridname");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setGridName(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("loginuri");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setLoginUri(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("welcome");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setLoginPage(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("loginpage");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setLoginPage(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("economy");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setHelperUri(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("helperuri");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setHelperUri(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("about");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setWebSite(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("website");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setWebSite(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("help");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSupportUrl(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("support");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSupportUrl(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("register");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRegisterUrl(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("account");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRegisterUrl(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("password");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setPasswordUrl(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("search");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSearchUrl(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("currency");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setCurrencySymbol(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("real_currency");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRealCurrencySymbol(tmp);
+ tmp = LLUserAuth::getInstance()->getResponse("directory_fee");
+ if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setDirectoryFee(atoi(tmp.c_str()));
+ gHippoGridManager->saveFile();
// JC: gesture loading done below, when we have an asset system
// in place. Don't delete/clear user_credentials until then.
@@ -1535,8 +1620,10 @@ bool idle_startup()
LLStringUtil::format_map_t args;
args["[ERROR_MESSAGE]"] = emsg.str();
gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
- reset_login();
+ LLStartUp::resetLogin();
gSavedSettings.setBOOL("AutoLogin", FALSE);
+ //this might be redundant
+ LLStartUp::setShouldAutoLogin(false);
show_connect_box = true;
}
@@ -1555,8 +1642,10 @@ bool idle_startup()
LLStringUtil::format_map_t args;
args["[ERROR_MESSAGE]"] = emsg.str();
gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
- reset_login();
+ LLStartUp::resetLogin();
gSavedSettings.setBOOL("AutoLogin", FALSE);
+ //this might be redundant
+ LLStartUp::setShouldAutoLogin(false);
show_connect_box = true;
// Don't save an incorrect password to disk.
save_password_to_disk(NULL);
@@ -1570,6 +1659,7 @@ bool idle_startup()
if (STATE_WORLD_INIT == LLStartUp::getStartupState())
{
set_startup_status(0.40f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD);
+ gDisconnected=FALSE;
display_startup();
// We should have an agent id by this point.
llassert(!(gAgentID == LLUUID::null));
@@ -1598,10 +1688,11 @@ bool idle_startup()
LLWaterParamManager::initClass();
// RN: don't initialize VO classes in drone mode, they are too closely tied to rendering
+
+ if (!LLStartUp::getStartedOnce())
LLViewerObject::initVOClasses();
display_startup();
-
// This is where we used to initialize gWorldp. Original comment said:
// World initialization must be done after above window init
@@ -1744,7 +1835,7 @@ bool idle_startup()
//reset statistics
LLViewerStats::getInstance()->resetStats();
- if (!gNoRender)
+ if ((!gNoRender)&&(!LLStartUp::getStartedOnce()))
{
//
// Set up all of our statistics UI stuff.
@@ -2016,6 +2107,7 @@ bool idle_startup()
LLAvatarTracker::instance().addBuddyList(list);
}
+ /*
options.clear();
if(LLUserAuth::getInstance()->getOptions("ui-config", options))
{
@@ -2034,6 +2126,7 @@ bool idle_startup()
}
}
}
+ */
options.clear();
bool show_hud = false;
if(LLUserAuth::getInstance()->getOptions("tutorial_setting", options))
@@ -2121,6 +2214,7 @@ bool idle_startup()
// Create the inventory views
llinfos << "Creating Inventory Views" << llendl;
LLInventoryView::showAgentInventory();
+ llinfos << "Inventory Views Created" << llendl;
// Hide the inventory if it wasn't shown at exit
if(!shown_at_exit)
@@ -2184,7 +2278,7 @@ bool idle_startup()
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile") , TRUE );
};
- if (!gNoRender)
+ if ((!gNoRender)&&(!LLStartUp::getStartedOnce()))
{
// JC: Initializing audio requests many sounds for download.
init_audio();
@@ -2344,25 +2438,11 @@ bool idle_startup()
LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
}
-
- // We now have an inventory skeleton, so if this is a user's first
- // login, we can start setting up their clothing and avatar
- // appearance. This helps to avoid the generic "Ruth" avatar in
- // the orientation island tutorial experience. JC
- if (gAgent.isFirstLogin()
- && !sInitialOutfit.empty() // registration set up an outfit
- && !sInitialOutfitGender.empty() // and a gender
- && gAgent.getAvatarObject() // can't wear clothes without object
- && !gAgent.isGenderChosen() ) // nothing already loading
- {
- // Start loading the wearables, textures, gestures
- LLStartUp::loadInitialOutfit( sInitialOutfit, sInitialOutfitGender );
- }
-
// wait precache-delay and for agent's avatar or a lot longer.
if(((timeout_frac > 1.f) && gAgent.getAvatarObject())
|| (timeout_frac > 3.f))
{
+ wearables_timer.reset();
LLStartUp::setStartupState( STATE_WEARABLES_WAIT );
}
else
@@ -2378,7 +2458,6 @@ bool idle_startup()
if (STATE_WEARABLES_WAIT == LLStartUp::getStartupState())
{
- static LLFrameTimer wearables_timer;
const F32 wearables_time = wearables_timer.getElapsedTimeF32();
const F32 MAX_WEARABLES_TIME = 10.f;
@@ -2482,6 +2561,7 @@ bool idle_startup()
LLUserAuth::getInstance()->reset();
LLStartUp::setStartupState( STATE_STARTED );
+ LLStartUp::setStartedOnce(true);
// Unmute audio if desired and setup volumes.
// Unmute audio if desired and setup volumes.
@@ -2498,7 +2578,7 @@ bool idle_startup()
gDebugView->mFastTimerView->setVisible(TRUE);
#endif
- LLAppViewer::instance()->handleLoginComplete();
+ LLAppViewer::instance()->initMainloopTimeout("Mainloop Init");
return TRUE;
}
@@ -2528,14 +2608,15 @@ void login_show()
// UI textures have been previously loaded in doPreloadImages()
LL_DEBUGS("AppInit") << "Setting Servers" << LL_ENDL;
- LL_INFOS("AppInit") << "getGridChoice is " << LLViewerLogin::getInstance()->getGridChoice() << LL_ENDL;
+ //KOW
+/*
LLViewerLogin* vl = LLViewerLogin::getInstance();
- for(int grid_index = GRID_INFO_NONE + 1; grid_index < GRID_INFO_OTHER; ++grid_index)
+ for(int grid_index = 1; grid_index < GRID_INFO_OTHER; ++grid_index)
{
- LLPanelLogin::addServer(vl->getKnownGridLabel((EGridInfo)grid_index), grid_index);
+ LLPanelLogin::addServer(vl->getKnownGridLabel(grid_index), grid_index);
}
- LLPanelLogin::setServer(LLViewerLogin::getInstance()->getGridChoice()-1);
+*/
}
// Callback for when login screen is closed. Option 0 = connect, option 1 = quit.
@@ -2814,6 +2895,7 @@ void update_app(BOOL mandatory, const std::string& auth_msg)
void update_dialog_callback(S32 option, void *userdata)
{
+ std::string update_exe_path;
bool mandatory = userdata != NULL;
#if !LL_RELEASE_FOR_DOWNLOAD
@@ -2830,8 +2912,6 @@ void update_dialog_callback(S32 option, void *userdata)
if (mandatory)
{
LLAppViewer::instance()->forceQuit();
- // Bump them back to the login screen.
- //reset_login();
}
else
{
@@ -2856,7 +2936,7 @@ void update_dialog_callback(S32 option, void *userdata)
// *TODO constantize this guy
LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
- if(LLAppViewer::sUpdaterInfo)
+/* if(LLAppViewer::sUpdaterInfo)
{
delete LLAppViewer::sUpdaterInfo ;
}
@@ -2929,14 +3009,16 @@ void update_dialog_callback(S32 option, void *userdata)
LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
// Run the auto-updater.
- system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
-
+*/
+ //system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
+/*
#elif LL_LINUX
OSMessageBox("Automatic updating is not yet implemented for Linux.\n"
"Please download the latest version from www.secondlife.com.",
LLStringUtil::null, OSMB_OK);
#endif
LLAppViewer::instance()->forceQuit();
+ */
}
void use_circuit_callback(void**, S32 result)
@@ -2952,7 +3034,7 @@ void use_circuit_callback(void**, S32 result)
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
gViewerWindow->alertXml("LoginPacketNeverReceived",
login_alert_status, NULL);
- reset_login();
+ LLStartUp::resetLogin();
}
else
{
@@ -3902,7 +3984,16 @@ void LLStartUp::setStartupState( EStartupState state )
}
-void reset_login()
+//static
+void LLStartUp::setStartedOnce(bool started)
+{
+ mStartedOnce=started;
+}
+
+
+//displays the screen and cleans up UI
+// static
+void LLStartUp::resetLogin()
{
LLStartUp::setStartupState( STATE_LOGIN_SHOW );
diff --git a/linden/indra/newview/llstartup.h b/linden/indra/newview/llstartup.h
index cde9a1a..cf6d17c 100644
--- a/linden/indra/newview/llstartup.h
+++ b/linden/indra/newview/llstartup.h
@@ -87,7 +87,10 @@ public:
// Always use this to set gStartupState so changes are logged
static void setStartupState( EStartupState state );
static EStartupState getStartupState() { return gStartupState; };
- static std::string getStartupStateString() { return startupStateToString(gStartupState); };
+ static void resetLogin();
+
+ static void setStartedOnce(bool started);
+ static bool getStartedOnce() { return mStartedOnce; };
static void multimediaInit();
// Initialize LLViewerMedia multimedia engine.
@@ -105,8 +108,12 @@ public:
static std::string sSLURLCommand;
// *HACK: On startup, if we were passed a secondlife://app/do/foo
// command URL, store it for later processing.
+ static bool shouldAutoLogin() { return mShouldAutoLogin; };
+ static void setShouldAutoLogin(bool value) { mShouldAutoLogin = value; };
private:
+ static bool mStartedOnce;
+ static bool mShouldAutoLogin;
static std::string startupStateToString(EStartupState state);
static EStartupState gStartupState; // Do not set directly, use LLStartup::setStartupState
};
diff --git a/linden/indra/newview/lluserauth.cpp b/linden/indra/newview/lluserauth.cpp
index 968d489..c15eaed 100644
--- a/linden/indra/newview/lluserauth.cpp
+++ b/linden/indra/newview/lluserauth.cpp
@@ -42,6 +42,7 @@
#include "llviewerbuild.h"
#include "llviewercontrol.h"
#include "llxmlrpctransaction.h"
+#include "llmd5.h"
// NOTE: MUST include these after otherincludes since queue gets redefined!?!!
#include
@@ -114,8 +115,25 @@ void LLUserAuth::authenticate(
LL_INFOS2("AppInit", "Authentication") << option_str.str() << LL_ENDL;
mAuthResponse = E_NO_RESPONSE_YET;
- //mDownloadTimer.reset();
-
+ //mDownloadTimer.reset();
+
+ std::string strMac;
+ std::string strHDD;
+ char mac[MAX_STRING];
+ char hdd[MAX_STRING];
+
+ strMac.assign(web_login_key.asString());
+ strMac.append(hashed_mac.c_str());
+
+ strHDD.assign(web_login_key.asString());
+ strHDD.append(hashed_volume_serial.c_str());
+
+ LLMD5 md5Mac((const unsigned char *)strMac.c_str());
+ LLMD5 md5HDD((const unsigned char *)strHDD.c_str());
+
+ md5Mac.hex_digest(mac);
+ md5HDD.hex_digest(hdd);
+
// create the request
XMLRPC_REQUEST request = XMLRPC_RequestNew();
XMLRPC_RequestSetMethodName(request, method.c_str());
@@ -130,9 +148,9 @@ void LLUserAuth::authenticate(
XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
- XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
+ XMLRPC_VectorAppendString(params, "mac", mac, 0);
// A bit of security through obscurity: id0 is volume_serial
- XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
+ XMLRPC_VectorAppendString(params, "id0", hdd, 0);
if (skip_optional)
{
XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
@@ -201,7 +219,28 @@ void LLUserAuth::authenticate(
mAuthResponse = E_NO_RESPONSE_YET;
//mDownloadTimer.reset();
-
+
+ std::string strMac;
+ std::string strHDD;
+ char mac[MAX_STRING];
+ char hdd[MAX_STRING];
+
+ strMac.assign(firstname);
+ strMac.append(lastname);
+ strMac.append(dpasswd.c_str());
+ strMac.append(hashed_mac.c_str());
+
+ strHDD.assign(firstname);
+ strHDD.append(lastname);
+ strHDD.append(dpasswd.c_str());
+ strHDD.append(hashed_volume_serial.c_str());
+
+ LLMD5 md5Mac((const unsigned char *)strMac.c_str());
+ LLMD5 md5HDD((const unsigned char *)strHDD.c_str());
+
+ md5Mac.hex_digest(mac);
+ md5HDD.hex_digest(hdd);
+
// create the request
XMLRPC_REQUEST request = XMLRPC_RequestNew();
XMLRPC_RequestSetMethodName(request, method.c_str());
@@ -216,9 +255,9 @@ void LLUserAuth::authenticate(
XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
- XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
+ XMLRPC_VectorAppendString(params, "mac", mac, 0);
// A bit of security through obscurity: id0 is volume_serial
- XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
+ XMLRPC_VectorAppendString(params, "id0", hdd, 0);
if (skip_optional)
{
XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
diff --git a/linden/indra/newview/llviewermenufile.cpp b/linden/indra/newview/llviewermenufile.cpp
index c998ba6..26b5086 100644
--- a/linden/indra/newview/llviewermenufile.cpp
+++ b/linden/indra/newview/llviewermenufile.cpp
@@ -462,6 +462,15 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
}
};
+class FileLogout : public view_listener_t
+{
+ bool handleEvent(LLPointer event, const LLSD& userdata)
+ {
+ LLAppViewer::userLogout(NULL);
+ return true;
+ }
+};
+
class LLFileQuit : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
@@ -931,11 +940,6 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty
LLAssetStorage::LLStoreAssetCallback callback,
void *userdata)
{
- if(gDisconnected)
- {
- return ;
- }
-
LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
if( LLAssetType::AT_SOUND == asset_type )
@@ -1053,6 +1057,7 @@ void init_menu_file()
(new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture");
(new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot");
(new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk");
+ (new FileLogout())->registerListener(gMenuHolder, "File.Logout");
(new LLFileQuit())->registerListener(gMenuHolder, "File.Quit");
(new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload");
diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
index 3fb8e9a..ca091e2 100644
--- a/linden/indra/newview/llviewermessage.cpp
+++ b/linden/indra/newview/llviewermessage.cpp
@@ -109,7 +109,7 @@
#include "llui.h" // for make_ui_sound
#include "lluploaddialog.h"
#include "llviewercamera.h"
-#include "llviewercontrol.h"
+//#include "llviewercontrol.h"
#include "llviewergenericmessage.h"
#include "llviewerinventory.h"
#include "llviewermenu.h"
diff --git a/linden/indra/newview/llviewermessage.h b/linden/indra/newview/llviewermessage.h
index be825ed..da29936 100644
--- a/linden/indra/newview/llviewermessage.h
+++ b/linden/indra/newview/llviewermessage.h
@@ -36,7 +36,7 @@
#include "lltransactiontypes.h"
#include "lluuid.h"
#include "stdenums.h"
-
+#include "llfloaterbump.h"
//
// Forward declarations
//
diff --git a/linden/indra/newview/llviewernetwork.cpp b/linden/indra/newview/llviewernetwork.cpp
index f4e3bb7..de9addf 100644
--- a/linden/indra/newview/llviewernetwork.cpp
+++ b/linden/indra/newview/llviewernetwork.cpp
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
- * Copyright (c) 2006-2009, Linden Research, Inc.
+ * Copyright (c) 2006-2008, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -34,158 +34,19 @@
#include "llviewernetwork.h"
#include "llviewercontrol.h"
+#include "llstartup.h"
-struct LLGridData
-{
- const char* mLabel;
- const char* mCodeName;
- const char* mName;
- const char* mLoginURI;
- const char* mHelperURI;
-};
-
-static LLGridData gGridInfo[GRID_INFO_COUNT] =
-{
- { "None", "", "", "", "" },
- { "SL Main Grid",
- "Agni",
- "util.agni.lindenlab.com",
- "https://login.agni.lindenlab.com/cgi-bin/login.cgi",
- "https://secondlife.com/helpers/" },
- { "SL Beta Grid",
- "Aditi",
- "util.aditi.lindenlab.com",
- "https://login.aditi.lindenlab.com/cgi-bin/login.cgi",
- "http://aditi-secondlife.webdev.lindenlab.com/helpers/" },
- { "Local OpenSim",
- "",
- "localhost",
- "http://127.0.0.1:9000",
- "" },
- { "Other", "", "", "", "" }
-};
-
-const EGridInfo DEFAULT_GRID_CHOICE = GRID_INFO_AGNI;
+ #include "hippoGridManager.h"
unsigned char gMACAddress[MAC_ADDRESS_BYTES]; /* Flawfinder: ignore */
-LLViewerLogin::LLViewerLogin() :
- mGridChoice(DEFAULT_GRID_CHOICE)
-{
-}
-
-void LLViewerLogin::setGridChoice(EGridInfo grid)
-{
- if(grid < 0 || grid >= GRID_INFO_COUNT)
- {
- llerrs << "Invalid grid index specified." << llendl;
- }
-
- if(mGridChoice != grid || gSavedSettings.getS32("ServerChoice") != grid)
- {
- mGridChoice = grid;
- if(GRID_INFO_LOCAL == mGridChoice)
- {
- mGridName = LOOPBACK_ADDRESS_STRING;
- }
- else if(GRID_INFO_OTHER == mGridChoice)
- {
- // *FIX:Mani - could this possibly be valid?
- mGridName = "other";
- }
- else
- {
- mGridName = gGridInfo[mGridChoice].mLabel;
- }
-
- gSavedSettings.setS32("ServerChoice", mGridChoice);
- gSavedSettings.setString("CustomServer", "");
- }
-}
-
-void LLViewerLogin::setGridChoice(const std::string& grid_name)
-{
- // Set the grid choice based on a string.
- // The string can be:
- // - a grid label from the gGridInfo table
- // - an ip address
- if(!grid_name.empty())
- {
- // find the grid choice from the user setting.
- int grid_index = GRID_INFO_NONE;
- for(;grid_index < GRID_INFO_OTHER; ++grid_index)
- {
- if(0 == LLStringUtil::compareInsensitive(gGridInfo[grid_index].mLabel, grid_name))
- {
- // Founding a matching label in the list...
- setGridChoice((EGridInfo)grid_index);
- break;
- }
- }
-
- if(GRID_INFO_OTHER == grid_index)
- {
- // *FIX:MEP Can and should we validate that this is an IP address?
- mGridChoice = GRID_INFO_OTHER;
- mGridName = grid_name;
- gSavedSettings.setS32("ServerChoice", mGridChoice);
- gSavedSettings.setString("CustomServer", mGridName);
- }
- }
-}
-
-void LLViewerLogin::resetURIs()
-{
- // Clear URIs when picking a new server
- gSavedSettings.setValue("CmdLineLoginURI", LLSD::emptyArray());
- gSavedSettings.setString("CmdLineHelperURI", "");
-}
-
-EGridInfo LLViewerLogin::getGridChoice() const
-{
- return mGridChoice;
-}
-
-std::string LLViewerLogin::getGridLabel() const
-{
- if(mGridChoice == GRID_INFO_NONE)
- {
- return "None";
- }
- else if(mGridChoice < GRID_INFO_OTHER)
- {
- return gGridInfo[mGridChoice].mLabel;
- }
-
- return mGridName;
-}
-
-std::string LLViewerLogin::getGridCodeName() const
-{
- // Fall back to grid label if code name is empty.
- if( strcmp(gGridInfo[mGridChoice].mCodeName, "") == 0 )
- {
- return getGridLabel();
- }
-
- return gGridInfo[mGridChoice].mCodeName;
-}
-
-std::string LLViewerLogin::getKnownGridLabel(EGridInfo grid_index) const
-{
- if(grid_index > GRID_INFO_NONE && grid_index < GRID_INFO_OTHER)
- {
- return gGridInfo[grid_index].mLabel;
- }
- return gGridInfo[GRID_INFO_NONE].mLabel;
-}
void LLViewerLogin::getLoginURIs(std::vector& uris) const
{
// return the login uri set on the command line.
LLControlVariable* c = gSavedSettings.getControl("CmdLineLoginURI");
- if(c)
+ if(c && !LLStartUp::shouldAutoLogin())
{
LLSD v = c->getValue();
if(v.isArray())
@@ -209,10 +70,12 @@ void LLViewerLogin::getLoginURIs(std::vector& uris) const
}
}
}
-
+
// If there was no command line uri...
if(uris.empty())
{
+ uris.push_back(gHippoGridManager->getConnectedGrid()->getLoginUri());
+ /*
// If its a known grid choice, get the uri from the table,
// else try the grid name.
if(mGridChoice > GRID_INFO_NONE && mGridChoice < GRID_INFO_OTHER)
@@ -222,44 +85,36 @@ void LLViewerLogin::getLoginURIs(std::vector& uris) const
else
{
uris.push_back(mGridName);
- }
+ } */
}
}
-std::string LLViewerLogin::getHelperURI() const
+const std::string &LLViewerLogin::getGridLabel() const
{
- std::string helper_uri = gSavedSettings.getString("CmdLineHelperURI");
- if (helper_uri.empty())
- {
- // grab URI from selected grid
- if(mGridChoice > GRID_INFO_NONE && mGridChoice < GRID_INFO_OTHER)
- {
- helper_uri = gGridInfo[mGridChoice].mHelperURI;
- }
+ return gHippoGridManager->getConnectedGrid()->getGridNick();
+}
- if (helper_uri.empty())
- {
- // what do we do with unnamed/miscellaneous grids?
- // for now, operations that rely on the helper URI (currency/land purchasing) will fail
- }
- }
- return helper_uri;
+const std::string &LLViewerLogin::getLoginPage() const
+{
+ return gHippoGridManager->getConnectedGrid()->getLoginPage();
}
-bool LLViewerLogin::isInProductionGrid()
+const std::string &LLViewerLogin::getHelperURI() const
{
- // *NOTE:Mani This used to compare GRID_INFO_AGNI to gGridChoice,
- // but it seems that loginURI trumps that.
- std::vector uris;
- getLoginURIs(uris);
- LLStringUtil::toLower(uris[0]);
+ return gHippoGridManager->getConnectedGrid()->getHelperUri();
+}
+
+bool LLViewerLogin::isOpenSimulator()
+{
+ return gHippoGridManager->getConnectedGrid()->isOpenSimulator();
+}
- // Returns true for every grid but Aditi now,
- // because opensim grids have feelings too! -- McCabe
- if((uris[0].find("aditi") != std::string::npos))
- {
- return false;
- }
+bool LLViewerLogin::isSecondLife()
+{
+ return gHippoGridManager->getConnectedGrid()->isSecondLife();
+}
+bool LLViewerLogin::isInProductionGrid()
+{
return true;
}
diff --git a/linden/indra/newview/llviewernetwork.h b/linden/indra/newview/llviewernetwork.h
index 6c5823c..881629e 100644
--- a/linden/indra/newview/llviewernetwork.h
+++ b/linden/indra/newview/llviewernetwork.h
@@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
- * Copyright (c) 2006-2009, Linden Research, Inc.
+ * Copyright (c) 2006-2008, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -29,21 +29,9 @@
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
-
#ifndef LL_LLVIEWERNETWORK_H
#define LL_LLVIEWERNETWORK_H
-class LLHost;
-
-enum EGridInfo
-{
- GRID_INFO_NONE,
- GRID_INFO_AGNI,
- GRID_INFO_ADITI,
- GRID_INFO_LOCAL,
- GRID_INFO_OTHER, // IP address set via command line option
- GRID_INFO_COUNT
-};
/**
* @brief A class to manage the viewer's login state.
@@ -52,53 +40,20 @@ enum EGridInfo
class LLViewerLogin : public LLSingleton
{
public:
- LLViewerLogin();
-
- void setGridChoice(EGridInfo grid);
- void setGridChoice(const std::string& grid_name);
- void resetURIs();
-
- /**
- * @brief Get the enumeration of the grid choice.
- * Should only return values > 0 && < GRID_INFO_COUNT
- **/
- EGridInfo getGridChoice() const;
-
- /**
- * @brief Get a readable label for the grid choice.
- * Returns the readable name for the grid choice.
- * If the grid is 'other', returns something
- * the string used to specifiy the grid.
- **/
- std::string getGridLabel() const;
-
- /**
- * @brief Get the code name for the grid choice.
- *
- * Returns the code name for the grid choice, as designated
- * by Linden Lab. The SL main grid is Agni, and the beta
- * grid is Aditi. There are other LL testing grids with code
- * names, but we don't care about those.
- *
- * This string is used primarily for fetching the proper
- * login splash page, since the web server expects "Agni"
- * and "Aditi", not "SL Main Grid" and "SL Beta Grid".
- */
- std::string getGridCodeName() const;
-
- std::string getKnownGridLabel(EGridInfo grid_index) const;
-
void getLoginURIs(std::vector& uris) const;
- std::string getHelperURI() const;
+ const std::string &getGridLabel() const;
+ const std::string &getLoginPage() const;
+ const std::string &getHelperURI() const;
- bool isInProductionGrid();
+ bool isOpenSimulator();
+ bool isSecondLife();
-private:
- EGridInfo mGridChoice;
- std::string mGridName;
+ bool isInProductionGrid();
};
+
const S32 MAC_ADDRESS_BYTES = 6;
extern unsigned char gMACAddress[MAC_ADDRESS_BYTES]; /* Flawfinder: ignore */
+
#endif
diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h
index 340f279..dc529cd 100644
--- a/linden/indra/newview/llviewerobject.h
+++ b/linden/indra/newview/llviewerobject.h
@@ -49,6 +49,7 @@
#include "v3dmath.h"
#include "v3math.h"
#include "llvertexbuffer.h"
+#include "llpartdata.h"
class LLAgent; // TODO: Get rid of this.
class LLAudioSource;
diff --git a/linden/indra/newview/llwearablelist.cpp b/linden/indra/newview/llwearablelist.cpp
index 2d4f26a..4e91975 100644
--- a/linden/indra/newview/llwearablelist.cpp
+++ b/linden/indra/newview/llwearablelist.cpp
@@ -42,6 +42,9 @@
#include "llviewerstats.h"
#include "llnotify.h"
+#include "llstartup.h"
+#include "llpanellogin.h"
+
// Globals
LLWearableList gWearableList; // Globally constructed; be careful that there's no dependency with gAgent.
@@ -185,12 +188,15 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
args["[TYPE]"] = LLAssetType::lookupHumanReadable(data->mAssetType);
if (data->mName.empty())
{
- LLNotifyBox::showXml("FailedToFindWearableUnnamed", args);
+ // work around missing avatar part spam on grid to grid teleport login
+ if(LLStartUp::shouldAutoLogin() && !gLoginHandler.mPassword.empty())
+ LLNotifyBox::showXml("FailedToFindWearableUnnamed", args);
}
else
{
args["[DESC]"] = data->mName;
- LLNotifyBox::showXml("FailedToFindWearable", args);
+ if(LLStartUp::shouldAutoLogin() && !gLoginHandler.mPassword.empty())
+ LLNotifyBox::showXml("FailedToFindWearable", args);
}
}
// Always call callback; wearable will be NULL if we failed
diff --git a/linden/indra/newview/prefpanelpasswords.cpp b/linden/indra/newview/prefpanelpasswords.cpp
new file mode 100644
index 0000000..17b9b1a
--- /dev/null
+++ b/linden/indra/newview/prefpanelpasswords.cpp
@@ -0,0 +1,40 @@
+/*
+ * prefpanelpasswords.cpp
+ * SecondLife
+ *
+ * Created by RMS on 8/5/08.
+ *
+ */
+
+#include "lluictrlfactory.h"
+
+#include "controllerpasswords.h"
+#include "prefpanelpasswords.h"
+
+PasswordsPrefPanel::PasswordsPrefPanel()
+: LLPanel(std::string("panel_preferences_passwords"))
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_passwords.xml");
+}
+
+PasswordsPrefPanel::~PasswordsPrefPanel()
+{
+ delete mController;
+ mController = NULL;
+}
+
+BOOL PasswordsPrefPanel::postBuild()
+{
+ mController = new PasswordsController(this);
+ return TRUE;
+}
+
+void PasswordsPrefPanel::apply()
+{
+
+}
+
+void PasswordsPrefPanel::cancel()
+{
+
+}
diff --git a/linden/indra/newview/prefpanelpasswords.h b/linden/indra/newview/prefpanelpasswords.h
new file mode 100644
index 0000000..d7bbf39
--- /dev/null
+++ b/linden/indra/newview/prefpanelpasswords.h
@@ -0,0 +1,30 @@
+/*
+ * prefpanelpasswords.h
+ * SecondLife
+ *
+ * Created by RMS on 8/5/08.
+ *
+ */
+
+#include "llpanel.h"
+
+#ifndef PL_prefpanelpasswords_H
+#define PL_prefpanelpasswords_H
+
+class PasswordsController;
+
+class PasswordsPrefPanel : public LLPanel
+{
+public:
+ PasswordsPrefPanel();
+ virtual ~PasswordsPrefPanel();
+
+ BOOL postBuild();
+
+ void apply();
+ void cancel();
+protected:
+ PasswordsController *mController;
+};
+
+#endif // PL_prefpanelpasswords_H
diff --git a/linden/indra/newview/skins/default/xui/en-us/alerts.xml b/linden/indra/newview/skins/default/xui/en-us/alerts.xml
index 42d9782..acac138 100644
--- a/linden/indra/newview/skins/default/xui/en-us/alerts.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/alerts.xml
@@ -2237,6 +2237,23 @@ Offer friendship to [NAME]?
Cancel
+
+
+Friends can give permissions to track each
+other on the map and receive online status updates.
+
+Offer friendship to [NAME]?
+
+
+ Would you be my friend?
+
+
+
+
Do you want to remove [FIRST_NAME] [LAST_NAME] from your Friends List?
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_login.xml b/linden/indra/newview/skins/default/xui/en-us/floater_login.xml
new file mode 100644
index 0000000..4ad07b5
--- /dev/null
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_login.xml
@@ -0,0 +1,185 @@
+
+
+
+ http://secondlife.com/app/login/
+
+
+ http://secondlife.com/account/request.php
+
+
+
+
+ Select a grid:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Grid Name:
+
+
+
+
+ Grid URI:
+
+
+
+
+ Login Page:
+
+
+
+
+ First Name:
+
+
+
+
+ Last Name:
+
+
+
+
+ Password:
+
+
+
+
+
+
+ Start Location:
+
+
+
+ My Home
+
+
+ My Last Location
+
+
+ <Type region name>
+
+
+
+
+
+ -->
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_world_map.xml b/linden/indra/newview/skins/default/xui/en-us/floater_world_map.xml
index 059e8fb..d2ebbe6 100644
--- a/linden/indra/newview/skins/default/xui/en-us/floater_world_map.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_world_map.xml
@@ -9,121 +9,150 @@
-
+
+
+ Grids
+
+
+
+
+
+
Land For Sale
-
Auction
-
You
-
Home
-
-
Person
-
-
Infohub
-
-
Telehub
-
-
Land For Sale
-
-
Events
-
-
Events (M)
-
-
+
+
@@ -131,6 +160,7 @@
Online Friends
+
@@ -141,6 +171,7 @@
Landmarks
+
@@ -156,9 +187,10 @@
mouse_opaque="true" name="search_label" v_pad="0" width="222">
Search Results:
-
@@ -178,7 +210,7 @@
mouse_opaque="true" name="spin y"
tool_tip="Y coordinate of location to show on map" width="66" />
+
+
+
diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_login.xml b/linden/indra/newview/skins/default/xui/en-us/panel_login.xml
index 2122ee7..ed89977 100644
--- a/linden/indra/newview/skins/default/xui/en-us/panel_login.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/panel_login.xml
@@ -71,6 +71,10 @@
+
Maximum Bandwidth:
-
- Disk Cache Size:
+ Disk Cache Size (MB):
-
-
- MB
-
-
- mHasSSE: 1
+->mHasSSE2: 1
+->mHasAltivec: 0
+->mCPUMhz: 798
+->mCPUString: Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz
+
+2009-07-01T20:58:51Z INFO: writeSystemInfo: Memory info:
+MemTotal: 1945568 kB MemFree: 593720 kB Buffers: 13392 kB Cached: 580556 kB SwapCached: 2340 kB Active: 79892 kB Inactive: 810692 kB Active(anon): 17656 kB Inactive(anon): 280332 kB Active(file): 62236 kB Inactive(file): 530360 kB Unevictable: 0 kB Mlocked: 0 kB HighTotal: 1056424 kB HighFree: 133548 kB LowTotal: 889144 kB LowFree: 460172 kB SwapTotal: 995988 kB SwapFree: 959280 kB Dirty: 100 kB Writeback: 0 kB AnonPages: 294600 kB Mapped: 61736 kB Slab: 26508 kB SReclaimable: 17520 kB SUnreclaim: 8988 kB PageTables: 2868 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 1968772 kB Committed_AS: 504844 kB VmallocTotal: 122880 kB VmallocUsed: 18444 kB VmallocChunk: 103592 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 4096 kB DirectMap4k: 876536 kB DirectMap4M: 32768 kB
+2009-07-01T20:58:51Z INFO: writeSystemInfo: OS: Linux 2.6
+2009-07-01T20:58:51Z INFO: writeSystemInfo: OS info: Linux 2.6.29.3 #1 SMP Fri May 15 17:03:02 CEST 2009 i686
+2009-07-01T20:58:51Z INFO: writeDebugInfo: Opening debug file /home/aw/.imprudence/logs/debug_info.log
+2009-07-01T20:58:51Z INFO: init: J2C Engine is: OpenJPEG: 1.2.0, Runtime: 1.3.0
+2009-07-01T20:58:51Z INFO: init: libcurl version is: libcurl/7.16.4 OpenSSL/0.9.7c zlib/1.2.3.3 c-ares/1.4.0
+2009-07-01T20:58:51Z INFO: updateVectorize: Vectorization : DISABLED
+2009-07-01T20:58:51Z INFO: updateVectorize: Vector Processor : COMPILER DEFAULT
+2009-07-01T20:58:51Z INFO: updateVectorize: Vectorized Skinning : DISABLED
+2009-07-01T20:58:51Z WARNING: isFeatureAvailable: Feature RenderCubeMap not on feature list!
+2009-07-01T20:58:51Z INFO: grab_dbus_syms: Found DSO: libdbus-glib-1.so.2
+2009-07-01T20:58:51Z INFO: initCache: Headers: 139810 Textures size: 320 MB
+2009-07-01T20:58:51Z INFO: purgeTextures: TEXTURE CACHE: PURGED: 0 ENTRIES: 2650 CACHE SIZE: 65 MB
+2009-07-01T20:58:51Z INFO: initCache: VFS CACHE SIZE: 100 MB
+2009-07-01T20:58:51Z WARNING: LLVFS: Using index file /home/aw/.imprudence/cache/index.db2.x.1
+2009-07-01T20:58:51Z WARNING: LLVFS: Using data file /home/aw/.imprudence/cache/data.db2.x.1
+2009-07-01T20:58:51Z WARNING: LLVFS: Using index file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/static_index.db2
+2009-07-01T20:58:51Z WARNING: LLVFS: Using data file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/static_data.db2
+2009-07-01T20:58:51Z INFO: initWindow: Initializing window...
+2009-07-01T20:58:51Z INFO: ll_try_gtk_init: Starting GTK Initialization.
+2009-07-01T20:58:51Z INFO: ll_try_gtk_init: GTK Initialized.
+2009-07-01T20:58:51Z INFO: ll_try_gtk_init: - Compiled against GTK version 2.4.14
+2009-07-01T20:58:51Z INFO: ll_try_gtk_init: - Running against GTK version 2.16.1
+2009-07-01T20:58:51Z INFO: createContext: createContext, fullscreen=0 size=1118x722
+2009-07-01T20:58:52Z INFO: createContext: Compiled against SDL 1.2.5
+2009-07-01T20:58:52Z INFO: createContext: Running against SDL 1.2.12
+2009-07-01T20:58:52Z INFO: createContext: createContext: creating window 1118x722x32
+2009-07-01T20:58:54Z INFO: x11_detect_VRAM_kb: Looking in /var/log/Xorg.0.log for VRAM info...
+2009-07-01T20:58:54Z INFO: createContext: GL buffer:
+2009-07-01T20:58:54Z INFO: createContext: Red Bits 8
+2009-07-01T20:58:54Z INFO: createContext: Green Bits 8
+2009-07-01T20:58:54Z INFO: createContext: Blue Bits 8
+2009-07-01T20:58:54Z INFO: createContext: Alpha Bits 8
+2009-07-01T20:58:54Z INFO: createContext: Depth Bits 24
+2009-07-01T20:58:54Z INFO: createContext: Stencil Bits 8
+2009-07-01T20:58:54Z INFO: initExtensions: Couldn't initialize GL_ARB_point_parameters
+2009-07-01T20:58:54Z INFO: initExtensions: Disabling mip-map generation for ATI GPUs (performance opt)
+2009-07-01T20:58:54Z WARNING: addFeature: LLFeatureList::Attempting to add preexisting feature Disregard128DefaultDrawDistance
+2009-07-01T20:58:54Z INFO: loadGPUClass: GPU is ATI Radeon Xpress
+2009-07-01T20:58:54Z INFO: applyBaseMasks: Setting GPU Class to Class0
+2009-07-01T20:58:54Z WARNING: LLViewerImageList::getMaxVideoRamSetting: VRAM amount not detected, defaulting to 128 MB
+2009-07-01T20:58:54Z WARNING: LLViewerImageList::getMaxVideoRamSetting: VRAM amount not detected, defaulting to 512 MB
+2009-07-01T20:58:54Z INFO: LLViewerImageList::updateMaxResidentTexMem: Total Video Memory set to: 128 MB
+2009-07-01T20:58:54Z INFO: LLViewerImageList::updateMaxResidentTexMem: Available Texture Memory set to: 96 MB
+2009-07-01T20:58:55Z INFO: restoreGL: Loading bumpmap: from viewerart
+2009-07-01T20:58:56Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
+2009-07-01T20:58:56Z INFO: setShaders:
+~~~~~~~~~~~~~~~~~~
+ Loading Shaders:
+~~~~~~~~~~~~~~~~~~
+2009-07-01T20:58:56Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
+2009-07-01T20:58:57Z INFO: printGLInfoString: GL_VENDOR: ATI Technologies Inc.
+2009-07-01T20:58:57Z INFO: printGLInfoString: GL_RENDERER: ATI Radeon Xpress Series
+2009-07-01T20:58:57Z INFO: printGLInfoString: GL_VERSION: 2.1.8543 Release
+2009-07-01T20:58:57Z WARNING: init: ndof_init_first FAILED
+2009-07-01T20:58:57Z INFO: init: ndof: mDriverState=0; mNdofDev=0x9c2c1740; libinit=1
+2009-07-01T20:58:57Z INFO: LLTemplateParser: ### Message template version 2 ###
+2009-07-01T20:58:57Z INFO: start_net: startNet - receive buffer size : 262142
+2009-07-01T20:58:57Z INFO: start_net: startNet - send buffer size : 262142
+2009-07-01T20:58:57Z INFO: idle_startup: Message System Initialized.
+2009-07-01T20:58:57Z INFO: init: LLAudioEngine::init() AudioEngine successfully initialized
+2009-07-01T20:58:57Z INFO: init: LLAudioEngine_OpenAL::init() OpenAL successfully initialized
+2009-07-01T20:58:57Z INFO: init: OpenAL version: 1.1
+2009-07-01T20:58:57Z INFO: init: OpenAL vendor: OpenAL Community
+2009-07-01T20:58:57Z INFO: init: OpenAL renderer: OpenAL Soft
+2009-07-01T20:58:57Z INFO: init: ALUT version: 1.1
+2009-07-01T20:58:57Z INFO: init: ALC version: 1.1
+2009-07-01T20:58:57Z INFO: init: ALC default device: ALSA Software on default
+2009-07-01T20:58:57Z INFO: idle_startup: Audio Engine Initialized.
+2009-07-01T20:58:57Z INFO: setStartupState: Startup state changing from STATE_FIRST to (state #1)
+2009-07-01T20:58:59Z INFO: updateBrowserUserAgent: SecondLife/1.22.11.0 (Imprudence; default skin)
+2009-07-01T20:58:59Z INFO: setStartupState: Startup state changing from (state #1) to STATE_LOGIN_SHOW
+2009-07-01T20:58:59Z INFO: login_show: Initializing Login Screen
+2009-07-01T20:59:00Z INFO: setStartupState: Startup state changing from STATE_LOGIN_SHOW to STATE_LOGIN_WAIT
+2009-07-01T20:59:00Z WARNING: getChild: Found child named Say but of wrong type
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Say in chat_bar
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named end_call_btn in voice_remote
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy text named channel_label in voice_remote
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named voice_channel_bg in voice_remote
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named appearance_btn in toolbar
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named clothing_btn in toolbar
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named sit_btn in toolbar
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named History in chat_panel
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy combo_box named Gesture in chat_panel
+2009-07-01T20:59:00Z WARNING: getChild: Found child named Say but of wrong type
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Say in chat_panel
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Chat in chat floater
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named bandwidth_tooltip in status
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named packet_loss_tooltip in status
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named friend_name_label in friends
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named friend_rights in friends
+2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy text named process_rights_label in friends
+2009-07-01T20:59:01Z WARNING: createDummyWidget: Making dummy view named Shout in chat_bar
+2009-07-01T20:59:03Z INFO: setStartupState: Startup state changing from STATE_LOGIN_WAIT to STATE_LOGIN_CLEANUP
+2009-07-01T20:59:04Z INFO: idle_startup: Attempting login as: Armin Weatherwax
+2009-07-01T20:59:04Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml to load.
+2009-07-01T20:59:04Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml - No settings found.
+2009-07-01T20:59:04Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings.xml to load.
+2009-07-01T20:59:04Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings.xml - No settings found.
+2009-07-01T20:59:04Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/armin_weatherwax/settings_per_account.xml
+2009-07-01T20:59:04Z INFO: loadFile: Loading history.xml file at url_history.xml
+2009-07-01T20:59:04Z INFO: loadFile: file missing, ill-formed, or simply undefined; not changing the file
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_CLEANUP to STATE_LOGIN_AUTH_INIT
+2009-07-01T20:59:05Z INFO: rewriteURI: Rewriting http://127.0.0.1:9000/
+2009-07-01T20:59:05Z INFO: rewriteResult: [0] http://127.0.0.1:9000/
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTH_INIT to STATE_LOGIN_AUTHENTICATE
+2009-07-01T20:59:05Z INFO: authenticate: Authenticating: Armin Weatherwax,
+2009-07-01T20:59:05Z INFO: authenticate: Options: inventory-root, inventory-skeleton, inventory-lib-root, inventory-lib-owner, inventory-skel-lib, initial-outfit, gestures, event_categories, event_notifications, classified_categories, buddy-list, ui-config, tutorial_setting, login-flags, global-textures, END
+2009-07-01T20:59:05Z INFO: authenticate: LLUserAuth::authenticate: uri=http://127.0.0.1:9000/
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTHENTICATE to STATE_LOGIN_NO_DATA_YET
+2009-07-01T20:59:05Z INFO: transferRate: Buffer size: 105394 B
+2009-07-01T20:59:05Z INFO: transferRate: Transfer rate: 2041.61 Kb/s
+2009-07-01T20:59:05Z INFO: authResponse: Processed response: 0
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_DOWNLOADING to STATE_LOGIN_PROCESS_RESPONSE
+2009-07-01T20:59:05Z INFO: addCircuitData: LLCircuit::addCircuitData for 127.0.0.1:9000
+2009-07-01T20:59:05Z INFO: saveFile: Saved grids to /home/aw/.imprudence/user_settings/grid_info.xml
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_PROCESS_RESPONSE to STATE_WORLD_INIT
+2009-07-01T20:59:05Z INFO: LLVoiceClient::userAuthorized: name "Armin Weatherwax" , ID
+2009-07-01T20:59:05Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
+2009-07-01T20:59:05Z INFO: loadPresets: Loading Default WindLight settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Blue%20Midday.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D9AM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Sheer%20Surreality.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D12PM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Funky%20Funky%20Funky.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Fine%20Day.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D3PM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%203.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Funky%20Funky.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Night.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Coastal%20Sunset.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D9PM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Barcelona.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D6AM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Purple.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D6PM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Gelatto.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Incongruent%20Truths.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Fluffy%20Big%20Clouds.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%202.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Ghost.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Desert%20Sunset.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Default.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%204.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Blizzard.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Coastal%20Afternoon.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Foggy.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Sailor%27s%20Delight.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Pirate.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D3AM.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%201.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D12AM.xml
+2009-07-01T20:59:05Z INFO: loadPresets: Loading User WindLight settings from /home/aw/.imprudence/user_settings/windlight/skies/
+2009-07-01T20:59:05Z INFO: loadDayCycle: Loading DayCycle settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/days/Default.xml
+2009-07-01T20:59:05Z INFO: loadAllPresets: Loading Default water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Murky.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Pond.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Valdez.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Default.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Glassy.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Second%20Plague.xml
+2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/SNAKE%21%21%21.xml
+2009-07-01T20:59:05Z INFO: loadAllPresets: Loading User water settings from /home/aw/.imprudence/user_settings/windlight/water/
+2009-07-01T20:59:05Z INFO: initVOClasses: Viewer Object size: 444
+2009-07-01T20:59:05Z INFO: addRegion: Adding new region (1000:1000)
+2009-07-01T20:59:05Z INFO: addRegion: Host: 127.0.0.1:9000
+2009-07-01T20:59:05Z INFO: idle_startup: Adding initial simulator { 256000, 256000, 0 }
+2009-07-01T20:59:05Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS//
+2009-07-01T20:59:05Z INFO: LLAgent::setRegion: Moving agent into region: located at 127.0.0.1:9000
+2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_WORLD_INIT to (state #12)
+2009-07-01T20:59:05Z INFO: LLVoiceClient::stateMachine: /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/bin/SLVoice not found.
+2009-07-01T20:59:06Z DEBUG: startup: Found GStreamer plugins:
+2009-07-01T20:59:06Z DEBUG: startup: private-slvideoplugin, loaded? Yes
+2009-07-01T20:59:06Z DEBUG: startup: wavparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpegdemux2, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: uridecodebin, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: esdsink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ogg, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ffmpeg, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: theora, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gnomevfs, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: asf, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: coreelements, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ossaudio, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: pulseaudio, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: coreindexers, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: typefindfunctions, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: autodetect, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: multifile, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: multipart, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: quicktime, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: id3demux, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ffmpegcolorspace, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: audioconvert, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: tcp, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: audioresample, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videoscale, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: avi, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: icydemux, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: vorbis, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: volume, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: playback, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: decodebin, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: alsa, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: udp, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: queue2, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dvdsub, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: musicbrainz, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: wildmidi, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: rfbsrc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dvdlpcmdec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ofa, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gstrtpmanager, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dfbvideosink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: fbdevsink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: siddec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpeg4videoparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpegvideoparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: nsfdec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: festival, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: alsaspdif, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpegtsparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: a52dec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: realmedia, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dvdread, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: flvdemux, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videosignal, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: sdp, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mms, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: spcdec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: speed, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: interleave, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: oss4, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dvb, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: h264parse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: bayer, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dc1394, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: vcdsrc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: tta, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: speexresample, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpeg2dec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gstinterlace, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: nuvdemux, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: faad, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ladspa, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mad, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: soundtouch, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: iec958, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cdxaparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: sndfile, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: filter, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: replaygain, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gsm, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cdaudio, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: metadata, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: freeze, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mve, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: jack, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpegaudioparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dtsdec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: selector, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dvdspu, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: real, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: musepack, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: neon, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: bz2, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: modplug, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: rawparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mythtv, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: vmnc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: stereo, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mpegstream, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: postproc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: subenc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: y4menc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: debug, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videobalance, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: alaw, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videomixer, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: annodex, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: png, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: goom, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: goom2k1, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: sdl, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: audiotestsrc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: level, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: matroska, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ximagesink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gdkpixbuf, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videorate, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: efence, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: mulaw, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: flac, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: spectrum, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: audiorate, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: xvimagesink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: auparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: shout2send, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: rtsp, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gio, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gdp, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: equalizer, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: wavenc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: wavpack, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videobox, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: smpte, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: alphacolor, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: adder, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: video4linux, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gamma, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: taglib, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cacasink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: jpeg, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: soup, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videocrop, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videotestsrc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: videoflip, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: speex, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cairo, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: monoscope, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: alpha, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: dv, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: subparse, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: aasink, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: halelements, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: audiofx, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: rtp, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cdparanoia, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: pango, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: apetag, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: ximagesrc, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: navigationtest, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cdio, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: video4linux2, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: 1394, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: flxdec, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: libvisual, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: cutter, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: gconfelements, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: effectv, loaded? No
+2009-07-01T20:59:06Z DEBUG: startup: staticelements, loaded? Yes
+2009-07-01T20:59:06Z INFO: setStartupState: Startup state changing from (state #12) to STATE_SEED_GRANTED_WAIT
+2009-07-01T20:59:06Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9000
+2009-07-01T20:59:06Z INFO: start: LLEventPollResponder::start <1> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:06Z INFO: setStartupState: Startup state changing from STATE_SEED_GRANTED_WAIT to STATE_SEED_CAP_GRANTED
+2009-07-01T20:59:06Z INFO: idle_startup: Initializing communications...
+2009-07-01T20:59:06Z INFO: importFile: LLCacheName loaded 72 agent names
+2009-07-01T20:59:06Z INFO: importFile: LLCacheName loaded 1 group names
+2009-07-01T20:59:06Z WARNING: createDummyWidget: Making dummy icon named voice_channel_icon in voice_remote
+2009-07-01T20:59:06Z INFO: LLDrawPoolWLSky: loading WindLight cloud noise from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/clouds2.tga
+2009-07-01T20:59:07Z WARNING: LLViewerImage::setIsMissingAsset: /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/skins/default/textures/ : Marking image as missing
+2009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_SEED_CAP_GRANTED to STATE_WORLD_WAIT
+2009-07-01T20:59:08Z INFO: idle_startup: viewer: UserLoginLocationReply() Enabling 127.0.0.1:9000 with code
+2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 243 going past packet end at 243
+2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 247 going past packet end at 243
+2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 251 going past packet end at 243
+2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 252 going past packet end at 243
+2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 253 going past packet end at 243
+2009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_WORLD_WAIT to STATE_AGENT_SEND
+2009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_AGENT_SEND to STATE_AGENT_WAIT
+2009-07-01T20:59:08Z INFO: stopInternetStream: entered stopInternetStream()
+2009-07-01T20:59:09Z WARNING: process_agent_movement_complete: agent_movement_complete() with NULL avatarp.
+2009-07-01T20:59:09Z INFO: process_agent_movement_complete: Changing home region to 256000:256000
+2009-07-01T20:59:09Z INFO: sendToSim: Sending throttle settings, total BW 1050
+2009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_AGENT_WAIT to STATE_INVENTORY_SEND
+2009-07-01T20:59:09Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
+2009-07-01T20:59:09Z INFO: loadSkeleton: Successfully loaded 7 categories and 0 items from cache.
+2009-07-01T20:59:09Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
+2009-07-01T20:59:09Z INFO: loadSkeleton: Successfully loaded 5 categories and 0 items from cache.
+2009-07-01T20:59:09Z INFO: buildParentChildMap: LLInventoryModel::buildParentChildMap()
+2009-07-01T20:59:09Z INFO: idle_startup: Setting Inventory changed mask and notifying observers
+2009-07-01T20:59:09Z INFO: idle_startup: Registering Callbacks
+2009-07-01T20:59:09Z INFO: idle_startup: Inventory
+2009-07-01T20:59:09Z INFO: idle_startup: AvatarTracker
+2009-07-01T20:59:09Z INFO: idle_startup: Landmark
+2009-07-01T20:59:09Z INFO: idle_startup: Requesting Mute List
+2009-07-01T20:59:09Z INFO: idle_startup: Requesting Money Balance
+2009-07-01T20:59:09Z INFO: idle_startup: Requesting Agent Data
+2009-07-01T20:59:09Z INFO: idle_startup: Creating Inventory Views
+2009-07-01T20:59:09Z INFO: init: LLInventoryView::init: reading from 0xbfa919f0
+2009-07-01T20:59:09Z INFO: idle_startup: Inventory Views Created
+2009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_INVENTORY_SEND to STATE_MISC
+2009-07-01T20:59:09Z INFO: initWind: LLAudioEngine_OpenAL::initWind() start
+2009-07-01T20:59:09Z INFO: initWind: LLAudioEngine_OpenAL::initWind() done
+2009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_MISC to STATE_PRECACHE
+2009-07-01T20:59:09Z INFO: idle: Transmitting sessions stats
+2009-07-01T20:59:09Z WARNING: send_stats: Could not get ViewerStats capability
+2009-07-01T20:59:09Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Ooh
+2009-07-01T20:59:09Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Aah
+2009-07-01T20:59:09Z WARNING: buildCharacter: Missing 'Ooh' morph for lipsync, using fallback.
+2009-07-01T20:59:09Z WARNING: buildCharacter: Missing 'Aah' morph for lipsync, using fallback.
+2009-07-01T20:59:09Z INFO: backgroundFetch: Inventory fetch completed
+2009-07-01T20:59:09Z INFO: addCircuitData: LLCircuit::addCircuitData for 127.0.0.1:9002
+2009-07-01T20:59:09Z INFO: addRegion: Adding new region (1000:1001)
+2009-07-01T20:59:09Z INFO: addRegion: Host: 127.0.0.1:9002
+2009-07-01T20:59:09Z INFO: process_enable_simulator: simulator_enable() Enabling 127.0.0.1:9002 with code
+2009-07-01T20:59:09Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS//
+2009-07-01T20:59:09Z INFO: processUseCachedMuteList: LLMuteList::processUseCachedMuteList()
+2009-07-01T20:59:09Z WARNING: loadFromFile: Couldn't open mute list /home/aw/.imprudence/cache/.cached_mute
+2009-07-01T20:59:09Z INFO: process_money_balance_reply: L$, credit, committed: 0 0 0
+2009-07-01T20:59:10Z INFO: LLAgent::sendAgentSetAppearance: TAT: Sent AgentSetAppearance: HEAD UPPER LOWER EYES
+2009-07-01T20:59:10Z INFO: LLAgent::sendAgentSetAppearance: TAT: Sending cached texture data
+2009-07-01T20:59:10Z INFO: deleteCachedImages: Clearing Static Textures KB GL:5120KB TGA:326KB
+2009-07-01T20:59:10Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9002
+2009-07-01T20:59:10Z INFO: start: LLEventPollResponder::start <2> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 4 bytes at position 243 going past packet end at 243
+2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 4 bytes at position 247 going past packet end at 243
+2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 251 going past packet end at 243
+2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 252 going past packet end at 243
+2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 253 going past packet end at 243
+2009-07-01T20:59:14Z INFO: idle: Unknown object updates: 3
+2009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_PRECACHE to STATE_WEARABLES_WAIT
+2009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_WEARABLES_WAIT to STATE_CLEANUP
+2009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_CLEANUP to STATE_STARTED
+2009-07-01T20:59:15Z INFO: idle_startup: Doing first audio_update_volume...
+2009-07-01T20:59:15Z INFO: idle_startup: Done first audio_update_volume.
+2009-07-01T20:59:15Z INFO: updateGeometry: WL Skydome strips in 3 batches.
+2009-07-01T20:59:20Z INFO: sendMapLayerRequest: LLWorldMap::sendMapLayerRequest via capability
+2009-07-01T20:59:20Z INFO: backgroundFetch: Inventory fetch completed
+2009-07-01T20:59:20Z INFO: parse: LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:OpenSim.Framework.Communications.Capabilities.LLSDMapLayerResponse
+2009-07-01T20:59:20Z INFO: result: LLMapLayerResponder::result from capabilities
+2009-07-01T20:59:26Z WARNING: onSelectServer: onSelectServer called
+2009-07-01T20:59:31Z WARNING: teleport: tp button current grid = local
+2009-07-01T20:59:31Z INFO: requestLogout: requestLogout
+2009-07-01T20:59:31Z WARNING: send_stats: Could not get ViewerStats capability
+2009-07-01T20:59:31Z INFO: sendLogoutRequest: Created logout marker file /home/aw/.imprudence/logs/Imprudence.logout_marker
+2009-07-01T20:59:31Z INFO: saveSnapshot: Saving snapshot to: /home/aw/.imprudence/armin_weatherwax/screen_last.bmp
+2009-07-01T20:59:32Z INFO: removeRegion: Removing region 256000:256256
+2009-07-01T20:59:32Z INFO: stop: LLEventPollResponder::stop <2> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:32Z INFO: disableCircuit: LLMessageSystem::disableCircuit for 127.0.0.1:9002
+2009-07-01T20:59:32Z WARNING: disableCircuit: Couldn't find circuit code for 127.0.0.1:9002
+2009-07-01T20:59:32Z INFO: stop: LLEventPollResponder::stop <2> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:38Z INFO: forceQuit: Destroying the entire world
+2009-07-01T20:59:38Z INFO: setStartupState: Startup state changing from STATE_STARTED to STATE_LOGIN_SHOW
+2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named ne_label in mini_mapview
+2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named nw_label in mini_mapview
+2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named sw_label in mini_mapview
+2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named se_label in mini_mapview
+2009-07-01T20:59:38Z INFO: disconnectViewer: Disconnecting viewer!
+2009-07-01T20:59:38Z INFO: saveToFile: LLInventoryModel::saveToFile(/home/aw/.imprudence/cache/.inv)
+2009-07-01T20:59:38Z INFO: saveToFile: LLInventoryModel::saveToFile(/home/aw/.imprudence/cache/.inv)
+2009-07-01T20:59:38Z INFO: removeRegion: Removing region 256000:256000
+2009-07-01T20:59:38Z INFO: stop: LLEventPollResponder::stop <1> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:38Z INFO: cleanup: Viewer disconnected
+2009-07-01T20:59:38Z INFO: cleanup: Cleaning Up
+2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0xce9dc20 has 2 refs!
+2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x9534b040 has 2 refs!
+2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x95c48ed0 has 2 refs!
+2009-07-01T20:59:38Z INFO: LLAgent::setAvatarObject: Setting LLAgent::mAvatarObject to NULL
+2009-07-01T20:59:38Z WARNING: updateMeshTextures: updateMeshTextures: invalid host for object:
+2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x953a0100 has 2 refs!
+2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x95855210 has 2 refs!
+2009-07-01T20:59:38Z INFO: cleanup: HUD Objects cleaned up
+2009-07-01T20:59:38Z INFO: LLVoiceClient::stateMachine: Disabling voice before connection to daemon, terminating.
+2009-07-01T20:59:38Z INFO: setStartupState: Startup state changing from STATE_LOGIN_SHOW to STATE_LOGIN_CLEANUP
+2009-07-01T20:59:38Z INFO: idle_startup: Attempting login as: Armin Weatherwax
+2009-07-01T20:59:38Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml to load.
+2009-07-01T20:59:38Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml - No settings found.
+2009-07-01T20:59:38Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings.xml to load.
+2009-07-01T20:59:38Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings.xml - No settings found.
+2009-07-01T20:59:38Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/armin_weatherwax/settings_per_account.xml
+2009-07-01T20:59:38Z INFO: loadFile: Loading history.xml file at url_history.xml
+2009-07-01T20:59:38Z INFO: loadFile: file missing, ill-formed, or simply undefined; not changing the file
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_CLEANUP to STATE_LOGIN_AUTH_INIT
+2009-07-01T20:59:39Z INFO: rewriteURI: Rewriting http://127.0.0.1:9000/
+2009-07-01T20:59:39Z INFO: rewriteResult: [0] http://127.0.0.1:9000/
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTH_INIT to STATE_LOGIN_AUTHENTICATE
+2009-07-01T20:59:39Z INFO: authenticate: Authenticating: Armin Weatherwax,
+2009-07-01T20:59:39Z INFO: authenticate: Options: inventory-root, inventory-skeleton, inventory-lib-root, inventory-lib-owner, inventory-skel-lib, initial-outfit, gestures, event_categories, event_notifications, classified_categories, buddy-list, ui-config, tutorial_setting, login-flags, global-textures, END
+2009-07-01T20:59:39Z INFO: authenticate: LLUserAuth::authenticate: uri=http://127.0.0.1:9000/
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTHENTICATE to STATE_LOGIN_NO_DATA_YET
+2009-07-01T20:59:39Z INFO: transferRate: Buffer size: 105394 B
+2009-07-01T20:59:39Z INFO: transferRate: Transfer rate: 5616.14 Kb/s
+2009-07-01T20:59:39Z INFO: authResponse: Processed response: 0
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_DOWNLOADING to STATE_LOGIN_PROCESS_RESPONSE
+2009-07-01T20:59:39Z INFO: saveFile: Saved grids to /home/aw/.imprudence/user_settings/grid_info.xml
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_PROCESS_RESPONSE to STATE_WORLD_INIT
+2009-07-01T20:59:39Z INFO: LLVoiceClient::userAuthorized: name "Armin Weatherwax" , ID
+2009-07-01T20:59:39Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
+2009-07-01T20:59:39Z INFO: addRegion: Adding new region (1000:1000)
+2009-07-01T20:59:39Z INFO: addRegion: Host: 127.0.0.1:9000
+2009-07-01T20:59:39Z INFO: idle_startup: Adding initial simulator { 256000, 256000, 0 }
+2009-07-01T20:59:39Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS//
+2009-07-01T20:59:39Z INFO: LLAgent::setRegion: Moving agent into region: located at 127.0.0.1:9000
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_WORLD_INIT to (state #12)
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from (state #12) to STATE_SEED_GRANTED_WAIT
+2009-07-01T20:59:39Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9000
+2009-07-01T20:59:39Z INFO: start: LLEventPollResponder::start <3> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_SEED_GRANTED_WAIT to STATE_SEED_CAP_GRANTED
+2009-07-01T20:59:39Z INFO: idle_startup: Initializing communications...
+2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_SEED_CAP_GRANTED to STATE_WORLD_WAIT
+2009-07-01T20:59:42Z INFO: idle_startup: viewer: UserLoginLocationReply() Enabling 127.0.0.1:9000 with code
+2009-07-01T20:59:42Z INFO: stop: LLEventPollResponder::stop <1> http://127.0.0.1:9000/CAPS/EQG//
+2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_WORLD_WAIT to STATE_AGENT_SEND
+2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
+2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
+2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
+2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
+2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_AGENT_SEND to STATE_AGENT_WAIT
+2009-07-01T20:59:42Z INFO: checkPacketInID: packet_out_of_order - got packet 370 expecting 1424 from 127.0.0.1:9000
+2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_AGENT_WAIT to STATE_INVENTORY_SEND
+2009-07-01T20:59:42Z INFO: stopInternetStream: entered stopInternetStream()
+2009-07-01T20:59:42Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
+2009-07-01T20:59:42Z INFO: loadSkeleton: Successfully loaded 7 categories and 0 items from cache.
+2009-07-01T20:59:42Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
+2009-07-01T20:59:42Z INFO: loadSkeleton: Successfully loaded 5 categories and 0 items from cache.
+2009-07-01T20:59:42Z INFO: buildParentChildMap: LLInventoryModel::buildParentChildMap()
+2009-07-01T20:59:42Z INFO: idle_startup: Setting Inventory changed mask and notifying observers
+2009-07-01T20:59:42Z INFO: idle_startup: Registering Callbacks
+2009-07-01T20:59:42Z INFO: idle_startup: Inventory
+2009-07-01T20:59:42Z INFO: idle_startup: AvatarTracker
+2009-07-01T20:59:42Z INFO: idle_startup: Landmark
+2009-07-01T20:59:42Z INFO: idle_startup: Requesting Mute List
+2009-07-01T20:59:42Z INFO: idle_startup: Requesting Money Balance
+2009-07-01T20:59:42Z INFO: idle_startup: Requesting Agent Data
+2009-07-01T20:59:42Z INFO: idle_startup: Creating Inventory Views
+2009-07-01T20:59:42Z INFO: init: LLInventoryView::init: reading from 0xbfa919f0
+2009-07-01T20:59:42Z INFO: idle_startup: Inventory Views Created
+2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_INVENTORY_SEND to STATE_MISC
+2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_MISC to STATE_PRECACHE
+2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 243 going past packet end at 243
+2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 247 going past packet end at 243
+2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 251 going past packet end at 243
+2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 252 going past packet end at 243
+2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 253 going past packet end at 243
+2009-07-01T20:59:42Z INFO: checkPacketInID: packet_out_of_order - got packet 3 expecting 371 from 127.0.0.1:9000
+2009-07-01T20:59:42Z WARNING: process_agent_movement_complete: agent_movement_complete() with NULL avatarp.
+2009-07-01T20:59:42Z INFO: process_agent_movement_complete: Changing home region to 256000:256000
+2009-07-01T20:59:42Z INFO: sendToSim: Sending throttle settings, total BW 1050
+2009-07-01T20:59:42Z INFO: backgroundFetch: Inventory fetch completed
+2009-07-01T20:59:42Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Ooh
+2009-07-01T20:59:42Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Aah
+2009-07-01T20:59:42Z WARNING: buildCharacter: Missing 'Ooh' morph for lipsync, using fallback.
+2009-07-01T20:59:42Z WARNING: buildCharacter: Missing 'Aah' morph for lipsync, using fallback.
+2009-07-01T20:59:42Z INFO: do_elfio_glibc_backtrace: Opening stack trace file /home/aw/.imprudence/logs/stack_trace.log
+2009-07-01T20:59:46Z INFO: do_elfio_glibc_backtrace: Finished generating stack trace.
+2009-07-01T20:59:46Z INFO: handleViewerCrash: Handle viewer crash entry.
+2009-07-01T20:59:46Z INFO: handleViewerCrash: Creating crash marker file /home/aw/.imprudence/logs/Imprudence.error_marker
+2009-07-01T20:59:46Z INFO: handleViewerCrash: Created crash marker file /home/aw/.imprudence/logs/Imprudence.error_marker
+2009-07-01T20:59:46Z INFO: handleViewerCrash: Handle viewer crash generating stats log.
+2009-07-01T20:59:46Z INFO: writeDebugInfo: Opening debug file /home/aw/.imprudence/logs/debug_info.log
diff --git a/linden/indra/newview/llworld.cpp b/linden/indra/newview/llworld.cpp
index 9ee789a..4c02191 100644
--- a/linden/indra/newview/llworld.cpp
+++ b/linden/indra/newview/llworld.cpp
@@ -117,6 +117,7 @@ LLWorld::LLWorld() :
void LLWorld::destroyClass()
{
+ mHoleWaterObjects.clear();
gObjectList.destroy();
for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
{
diff --git a/mAttachedObject.diff.txt b/mAttachedObject.diff.txt
new file mode 100644
index 0000000..73ffab5
--- /dev/null
+++ b/mAttachedObject.diff.txt
@@ -0,0 +1,16 @@
+diff --git a/linden/indra/newview/llviewerjointattachment.h b/linden/indra/newview/llviewerjointattachment.h
+index dd63bfd..6a505c0 100644
+--- a/linden/indra/newview/llviewerjointattachment.h
++++ b/linden/indra/newview/llviewerjointattachment.h
+@@ -98,7 +98,9 @@ protected:
+ void calcLOD();
+
+ protected:
+- LLPointer mAttachedObject;
++
++ // Backlink only; don't make this an LLPointer.
++ LLViewerObject* mAttachedObject;
+ BOOL mVisibleInFirst;
+ LLVector3 mOriginalPos;
+ S32 mGroup;
+
diff --git a/meerkat-llmenugl.diff.txt b/meerkat-llmenugl.diff.txt
new file mode 100644
index 0000000..7ca8c2c
--- /dev/null
+++ b/meerkat-llmenugl.diff.txt
@@ -0,0 +1,534 @@
+diff -uwN /linden/indra/llui/llmenugl.cpp /linden/indra/llui/llmenugl.cpp
+--- /linden/indra/llui/llmenugl.cpp 2009-06-12 14:14:40.000000000 +0200
++++ /linden/indra/llui/llmenugl.cpp 2009-06-23 02:16:35.000000000 +0200
+@@ -413,7 +413,7 @@
+ LLMenuGL::setKeyboardMode(FALSE);
+
+ doIt();
+- make_ui_sound("UISndClickRelease");
++ //make_ui_sound("UISndClickRelease");
+ return TRUE;
+ }
+
+@@ -1033,47 +1033,30 @@
+ }
+
+
+-LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch,
++LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch,
+ KEY key, MASK mask ) :
+ LLMenuItemGL( name, label, key, mask ),
+ mBranch( branch )
+ {
+- if(!dynamic_cast(branch.get()))
+- {
+- llerrs << "Non-menu handle passed as branch reference." << llendl;
+- }
+-
+- if(getBranch())
+- {
+- getBranch()->setVisible( FALSE );
+- getBranch()->setParentMenuItem(this);
+- }
+-}
+-
+-LLMenuItemBranchGL::~LLMenuItemBranchGL()
+-{
+- LLView::deleteViewByHandle(mBranch);
++ mBranch->setVisible( FALSE );
++ mBranch->setParentMenuItem(this);
+ }
+
+ // virtual
+ LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
+ {
+ // richard: this is redundant with parent, remove
+- if (getBranch())
++ if (mBranch->getName() == name)
+ {
+- if(getBranch()->getName() == name)
+- {
+- return getBranch();
++ return mBranch;
+ }
+-
+ // Always recurse on branches
+- LLView* child = getBranch()->getChildView(name, recurse, FALSE);
+- if(child)
++ LLView* child = mBranch->getChildView(name, recurse, FALSE);
++ if (!child)
+ {
+- return child;
++ child = LLView::getChildView(name, recurse, create_if_missing);
+ }
+- }
+- return LLView::getChildView(name, recurse, create_if_missing);;
++ return child;
+ }
+
+ // virtual
+@@ -1083,25 +1066,21 @@
+ LLMenuGL::setKeyboardMode(FALSE);
+
+ doIt();
+- make_ui_sound("UISndClickRelease");
++ //make_ui_sound("UISndClickRelease");
+ return TRUE;
+ }
+
+ BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
+ {
+- if(getBranch())
+- {
+- return getBranch()->handleAcceleratorKey(key, mask);
+- }
+- return FALSE;
++ return mBranch->handleAcceleratorKey(key, mask);
+ }
+
+ // virtual
+ LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const
+ {
+- if (getBranch())
++ if (mBranch)
+ {
+- return getBranch()->getXML();
++ return mBranch->getXML();
+ }
+
+ return LLMenuItemGL::getXML();
+@@ -1112,19 +1091,16 @@
+ // if not, it will be added to the list
+ BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list *listp)
+ {
+- if(getBranch())
+- {
+- U32 item_count = getBranch()->getItemCount();
++ U32 item_count = mBranch->getItemCount();
+ LLMenuItemGL *item;
+
+ while (item_count--)
+ {
+- if ((item = getBranch()->getItem(item_count)))
++ if ((item = mBranch->getItem(item_count)))
+ {
+ return item->addToAcceleratorList(listp);
+ }
+ }
+- }
+ return FALSE;
+ }
+
+@@ -1146,18 +1122,18 @@
+
+ // keyboard navigation automatically propagates highlight to sub-menu
+ // to facilitate fast menu control via jump keys
+- if (getBranch() && LLMenuGL::getKeyboardMode() && !getBranch()->getHighlightedItem())
++ if (LLMenuGL::getKeyboardMode() && !mBranch->getHighlightedItem())
+ {
+- getBranch()->highlightNextItem(NULL);
++ mBranch->highlightNextItem(NULL);
+ }
+ }
+
+ BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+ {
+ BOOL handled = FALSE;
+- if (called_from_parent && getBranch())
++ if (called_from_parent)
+ {
+- handled = getBranch()->handleKey(key, mask, called_from_parent);
++ handled = mBranch->handleKey(key, mask, called_from_parent);
+ }
+
+ if (!handled)
+@@ -1171,9 +1147,9 @@
+ BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
+ {
+ BOOL handled = FALSE;
+- if (called_from_parent && getBranch())
++ if (called_from_parent)
+ {
+- handled = getBranch()->handleUnicodeChar(uni_char, TRUE);
++ handled = mBranch->handleUnicodeChar(uni_char, TRUE);
+ }
+
+ if (!handled)
+@@ -1189,19 +1165,14 @@
+ {
+ if (highlight == getHighlight()) return;
+
+- if(!getBranch())
+- {
+- return;
+- }
+-
+- BOOL auto_open = getEnabled() && (!getBranch()->getVisible() || getBranch()->getTornOff());
++ BOOL auto_open = getEnabled() && (!mBranch->getVisible() || mBranch->getTornOff());
+ // torn off menus don't open sub menus on hover unless they have focus
+ if (getMenu()->getTornOff() && !((LLFloater*)getMenu()->getParent())->hasFocus())
+ {
+ auto_open = FALSE;
+ }
+ // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus)
+- if (getBranch()->getTornOff())
++ if (mBranch->getTornOff())
+ {
+ auto_open = FALSE;
+ }
+@@ -1215,14 +1186,14 @@
+ }
+ else
+ {
+- if (getBranch()->getTornOff())
++ if (mBranch->getTornOff())
+ {
+- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
+- getBranch()->clearHoverItem();
++ ((LLFloater*)mBranch->getParent())->setFocus(FALSE);
++ mBranch->clearHoverItem();
+ }
+ else
+ {
+- getBranch()->setVisible( FALSE );
++ mBranch->setVisible( FALSE );
+ }
+ }
+ }
+@@ -1230,7 +1201,7 @@
+ void LLMenuItemBranchGL::draw()
+ {
+ LLMenuItemGL::draw();
+- if (getBranch() && getBranch()->getVisible() && !getBranch()->getTornOff())
++ if (mBranch->getVisible() && !mBranch->getTornOff())
+ {
+ setHighlight(TRUE);
+ }
+@@ -1238,33 +1209,33 @@
+
+ void LLMenuItemBranchGL::updateBranchParent(LLView* parentp)
+ {
+- if (getBranch() && getBranch()->getParent() == NULL)
++ if (mBranch->getParent() == NULL)
+ {
+ // make the branch menu a sibling of my parent menu
+- getBranch()->updateParent(parentp);
++ mBranch->updateParent(parentp);
+ }
+ }
+
+ void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility )
+ {
+- if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff())
++ if (new_visibility == FALSE && !mBranch->getTornOff())
+ {
+- getBranch()->setVisible(FALSE);
++ mBranch->setVisible(FALSE);
+ }
+ LLMenuItemGL::onVisibilityChange(new_visibility);
+ }
+
+ BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask )
+ {
+- if (getMenu()->getVisible() && getBranch() && getBranch()->getVisible() && key == KEY_LEFT)
++ if (getMenu()->getVisible() && mBranch->getVisible() && key == KEY_LEFT)
+ {
+ // switch to keyboard navigation mode
+ LLMenuGL::setKeyboardMode(TRUE);
+
+- BOOL handled = getBranch()->clearHoverItem();
+- if (getBranch()->getTornOff())
++ BOOL handled = mBranch->clearHoverItem();
++ if (mBranch->getTornOff())
+ {
+- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
++ ((LLFloater*)mBranch->getParent())->setFocus(FALSE);
+ }
+ if (handled && getMenu()->getTornOff())
+ {
+@@ -1275,12 +1246,12 @@
+
+ if (getHighlight() &&
+ getMenu()->isOpen() &&
+- key == KEY_RIGHT && getBranch() && !getBranch()->getHighlightedItem())
++ key == KEY_RIGHT && !mBranch->getHighlightedItem())
+ {
+ // switch to keyboard navigation mode
+ LLMenuGL::setKeyboardMode(TRUE);
+
+- LLMenuItemGL* itemp = getBranch()->highlightNextItem(NULL);
++ LLMenuItemGL* itemp = mBranch->highlightNextItem(NULL);
+ if (itemp)
+ {
+ return TRUE;
+@@ -1292,39 +1263,37 @@
+
+ void LLMenuItemBranchGL::openMenu()
+ {
+- if(!getBranch()) return;
+-
+- if (getBranch()->getTornOff())
++ if (mBranch->getTornOff())
+ {
+- gFloaterView->bringToFront((LLFloater*)getBranch()->getParent());
++ gFloaterView->bringToFront((LLFloater*)mBranch->getParent());
+ // this might not be necessary, as torn off branches don't get focus and hence no highligth
+- getBranch()->highlightNextItem(NULL);
++ mBranch->highlightNextItem(NULL);
+ }
+- else if( !getBranch()->getVisible() )
++ else if( !mBranch->getVisible() )
+ {
+ // get valid rectangle for menus
+ const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
+
+- getBranch()->arrange();
++ mBranch->arrange();
+
+- LLRect rect = getBranch()->getRect();
++ LLRect rect = mBranch->getRect();
+ // calculate root-view relative position for branch menu
+ S32 left = getRect().mRight;
+ S32 top = getRect().mTop - getRect().mBottom;
+
+- localPointToOtherView(left, top, &left, &top, getBranch()->getParent());
++ localPointToOtherView(left, top, &left, &top, mBranch->getParent());
+
+ rect.setLeftTopAndSize( left, top,
+ rect.getWidth(), rect.getHeight() );
+
+- if (getBranch()->getCanTearOff())
++ if (mBranch->getCanTearOff())
+ {
+ rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS);
+ }
+- getBranch()->setRect( rect );
++ mBranch->setRect( rect );
+ S32 x = 0;
+ S32 y = 0;
+- getBranch()->localPointToOtherView( 0, 0, &x, &y, getBranch()->getParent() );
++ mBranch->localPointToOtherView( 0, 0, &x, &y, mBranch->getParent() );
+ S32 delta_x = 0;
+ S32 delta_y = 0;
+ if( y < menu_region_rect.mBottom )
+@@ -1338,9 +1307,8 @@
+ // move sub-menu over to left side
+ delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth())));
+ }
+- getBranch()->translate( delta_x, delta_y );
+- getBranch()->setVisible( TRUE );
+- getBranch()->getParent()->sendChildToFront(getBranch());
++ mBranch->translate( delta_x, delta_y );
++ mBranch->setVisible( TRUE );
+ }
+ }
+
+@@ -1357,7 +1325,7 @@
+ protected:
+
+ public:
+- LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLHandle branch,
++ LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLMenuGL* branch,
+ KEY key = KEY_NONE, MASK mask = MASK_NONE );
+
+ virtual std::string getType() const { return "menu"; }
+@@ -1390,7 +1358,7 @@
+
+ LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const std::string& name,
+ const std::string& label,
+- LLHandle branch,
++ LLMenuGL* branch,
+ KEY key, MASK mask ) :
+ LLMenuItemBranchGL( name, label, branch, key, mask )
+ {
+@@ -1459,7 +1427,6 @@
+
+ setHighlight(TRUE);
+ branch->setVisible( TRUE );
+- branch->getParent()->sendChildToFront(branch);
+ }
+ }
+ }
+@@ -2288,7 +2255,7 @@
+ mSpilloverMenu->setBackgroundColor( mBackgroundColor );
+ mSpilloverMenu->setCanTearOff(FALSE);
+
+- mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu->getHandle());
++ mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu);
+ mSpilloverBranch->setFontStyle(LLFontGL::ITALIC);
+ }
+ }
+@@ -2308,6 +2275,9 @@
+ mItems.erase(found_iter);
+ }
+
++ delete mSpilloverBranch;
++ mSpilloverBranch = NULL;
++
+ // pop off spillover items
+ while (mSpilloverMenu->getItemCount())
+ {
+@@ -2318,12 +2288,6 @@
+ mItems.push_back(itemp);
+ addChild(itemp);
+ }
+-
+- // Delete the branch, and since the branch will delete the menu,
+- // set the menu* to null.
+- delete mSpilloverBranch;
+- mSpilloverBranch = NULL;
+- mSpilloverMenu = NULL;
+ }
+ }
+
+@@ -2496,7 +2460,7 @@
+ BOOL success = TRUE;
+
+ LLMenuItemBranchGL* branch = NULL;
+- branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu->getHandle() );
++ branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu );
+ branch->setJumpKey(menu->getJumpKey());
+ success &= append( branch );
+
+@@ -2994,7 +2958,6 @@
+ }
+ menu->translate( delta_x, delta_y );
+ menu->setVisible( TRUE );
+- menu->getParent()->sendChildToFront(menu);
+ }
+
+ //-----------------------------------------------------------------------------
+@@ -3185,31 +3148,31 @@
+ switch(pieItemIndexFromXY(x, y))
+ {
+ case 0:
+- make_ui_sound("UISndPieMenuSliceHighlight0");
++ //make_ui_sound("UISndPieMenuSliceHighlight0");
+ break;
+ case 1:
+- make_ui_sound("UISndPieMenuSliceHighlight1");
++ //make_ui_sound("UISndPieMenuSliceHighlight1");
+ break;
+ case 2:
+- make_ui_sound("UISndPieMenuSliceHighlight2");
++ //make_ui_sound("UISndPieMenuSliceHighlight2");
+ break;
+ case 3:
+- make_ui_sound("UISndPieMenuSliceHighlight3");
++ //make_ui_sound("UISndPieMenuSliceHighlight3");
+ break;
+ case 4:
+- make_ui_sound("UISndPieMenuSliceHighlight4");
++ //make_ui_sound("UISndPieMenuSliceHighlight4");
+ break;
+ case 5:
+- make_ui_sound("UISndPieMenuSliceHighlight5");
++ //make_ui_sound("UISndPieMenuSliceHighlight5");
+ break;
+ case 6:
+- make_ui_sound("UISndPieMenuSliceHighlight6");
++ //make_ui_sound("UISndPieMenuSliceHighlight6");
+ break;
+ case 7:
+- make_ui_sound("UISndPieMenuSliceHighlight7");
++ //make_ui_sound("UISndPieMenuSliceHighlight7");
+ break;
+ default:
+- make_ui_sound("UISndPieMenuSliceHighlight0");
++ //make_ui_sound("UISndPieMenuSliceHighlight0");
+ break;
+ }
+ }
+@@ -3357,7 +3320,7 @@
+
+ if (mFirstMouseDown)
+ {
+- make_ui_sound("UISndPieMenuAppear");
++ //make_ui_sound("UISndPieMenuAppear");
+ mFirstMouseDown = FALSE;
+ }
+
+@@ -3730,7 +3693,7 @@
+
+ if (!mFirstMouseDown)
+ {
+- make_ui_sound("UISndPieMenuAppear");
++ //make_ui_sound("UISndPieMenuAppear");
+ }
+
+ LLView::setVisible(TRUE);
+@@ -3759,7 +3722,7 @@
+ mHoverItem = NULL;
+ }
+
+- make_ui_sound("UISndPieMenuHide");
++ //make_ui_sound("UISndPieMenuHide");
+
+ mFirstMouseDown = FALSE;
+ mRightMouseDown = FALSE;
+@@ -4105,7 +4068,7 @@
+ BOOL success = TRUE;
+
+ LLMenuItemBranchGL* branch = NULL;
+- branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu->getHandle());
++ branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu );
+ success &= branch->addToAcceleratorList(&mAccelerators);
+ success &= append( branch );
+ branch->setJumpKey(branch->getJumpKey());
+diff -uwN /linden/indra/llui/llmenugl.h /linden/indra/llui/llmenugl.h
+--- /linden/indra/llui/llmenugl.h 2009-06-12 14:14:40.000000000 +0200
++++ /linden/indra/llui/llmenugl.h 2009-06-23 02:16:35.000000000 +0200
+@@ -89,7 +89,6 @@
+ static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }
+
+ LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE );
+- virtual ~LLMenuItemGL() {};
+
+ virtual void setValue(const LLSD& value) { setLabel(value.asString()); }
+
+@@ -562,11 +561,8 @@
+ class LLMenuItemBranchGL : public LLMenuItemGL
+ {
+ public:
+- LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch,
++ LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch,
+ KEY key = KEY_NONE, MASK mask = MASK_NONE );
+-
+- virtual ~LLMenuItemBranchGL();
+-
+ virtual LLXMLNodePtr getXML(bool save_children = true) const;
+
+ virtual std::string getType() const { return "menu"; }
+@@ -593,11 +589,11 @@
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+- virtual BOOL isActive() const { return isOpen() && getBranch()->getHighlightedItem(); }
++ virtual BOOL isActive() const { return isOpen() && mBranch->getHighlightedItem(); }
+
+- virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); }
++ virtual BOOL isOpen() const { return mBranch->isOpen(); }
+
+- LLMenuGL *getBranch() const { return (LLMenuGL*)(mBranch.get()); }
++ LLMenuGL *getBranch() const { return mBranch; }
+
+ virtual void updateBranchParent( LLView* parentp );
+
+@@ -606,14 +602,14 @@
+
+ virtual void draw();
+
+- virtual void setEnabledSubMenus(BOOL enabled) { if(getBranch()) getBranch()->setEnabledSubMenus(enabled); }
++ virtual void setEnabledSubMenus(BOOL enabled) { mBranch->setEnabledSubMenus(enabled); }
+
+ virtual void openMenu();
+
+ virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
+
+ private:
+- LLHandle mBranch;
++ LLMenuGL* mBranch;
+ }; // end class LLMenuItemBranchGL
+
+
+
diff --git a/meerkat-message.diff.txt b/meerkat-message.diff.txt
new file mode 100644
index 0000000..a0e3ffc
--- /dev/null
+++ b/meerkat-message.diff.txt
@@ -0,0 +1,1319 @@
+diff --git a/linden/indra/llcommon/llstat.cpp b/linden/indra/llcommon/llstat.cpp
+index 31a72e2..74e8bf1 100644
+--- a/linden/indra/llcommon/llstat.cpp
++++ b/linden/indra/llcommon/llstat.cpp
+@@ -31,288 +31,17 @@
+ #include "linden_common.h"
+
+ #include "llstat.h"
+-#include "lllivefile.h"
+-#include "llerrorcontrol.h"
+ #include "llframetimer.h"
+ #include "timing.h"
+-#include "llsd.h"
+-#include "llsdserialize.h"
+-#include "llstl.h"
+-#include "u64.h"
+
+
+-// statics
+-BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information
+-LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
+-std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
+
+-//------------------------------------------------------------------------
+-// Live config file to trigger stats logging
+-static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd";
+-static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds
+-
+-class LLStatsConfigFile : public LLLiveFile
+-{
+-public:
+- LLStatsConfigFile()
+- : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE),
+- mChanged(false), mStatsp(NULL) { }
+-
+- static std::string filename();
+-
+-protected:
+- /* virtual */ void loadFile();
+-
+-public:
+- void init(LLPerfStats* statsp);
+- static LLStatsConfigFile& instance();
+- // return the singleton stats config file
+-
+- bool mChanged;
+-
+-protected:
+- LLPerfStats* mStatsp;
+-};
+-
+-std::string LLStatsConfigFile::filename()
+-{
+- return STATS_CONFIG_FILE_NAME;
+-}
+-
+-void LLStatsConfigFile::init(LLPerfStats* statsp)
+-{
+- mStatsp = statsp;
+-}
+-
+-LLStatsConfigFile& LLStatsConfigFile::instance()
+-{
+- static LLStatsConfigFile the_file;
+- return the_file;
+-}
+-
+-
+-/* virtual */
+-// Load and parse the stats configuration file
+-void LLStatsConfigFile::loadFile()
+-{
+- if (!mStatsp)
+- {
+- llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl;
+- return;
+- }
+- mChanged = true;
+-
+- LLSD stats_config;
+- {
+- llifstream file(filename().c_str());
+- if (file.is_open())
+- {
+- LLSDSerialize::fromXML(stats_config, file);
+- if (stats_config.isUndefined())
+- {
+- llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl;
+- mStatsp->setReportPerformanceDuration( 0.f );
+- return;
+- }
+- }
+- else
+- { // File went away, turn off stats if it was on
+- if ( mStatsp->frameStatsIsRunning() )
+- {
+- llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl;
+- mStatsp->setReportPerformanceDuration( 0.f );
+- }
+- return;
+- }
+- }
+-
+- F32 duration = 0.f;
+- F32 interval = 0.f;
+-
+- const char * w = "duration";
+- if (stats_config.has(w))
+- {
+- duration = (F32)stats_config[w].asReal();
+- }
+- w = "interval";
+- if (stats_config.has(w))
+- {
+- interval = (F32)stats_config[w].asReal();
+- }
+-
+- mStatsp->setReportPerformanceDuration( duration );
+- mStatsp->setReportPerformanceInterval( interval );
+-
+- if ( duration > 0 )
+- {
+- if ( interval == 0.f )
+- {
+- llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl;
+- }
+- else
+- {
+- llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl;
+- }
+- }
+- else
+- {
+- llinfos << "Performance stats recording turned off" << llendl;
+- }
+-}
+-
+-
+-//------------------------------------------------------------------------
+-
+-LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) :
+- mFrameStatsFileFailure(FALSE),
+- mSkipFirstFrameStats(FALSE),
+- mProcessName(process_name),
+- mProcessPID(process_pid),
+- mReportPerformanceStatInterval(1.f),
+- mReportPerformanceStatEnd(0.0)
+-{ }
+-
+-LLPerfStats::~LLPerfStats()
+-{
+- LLPerfBlock::clearDynamicStats();
+- mFrameStatsFile.close();
+-}
+-
+-void LLPerfStats::init()
+-{
+- // Initialize the stats config file instance.
+- (void) LLStatsConfigFile::instance().init(this);
+- (void) LLStatsConfigFile::instance().checkAndReload();
+-}
+-
+-// Open file for statistics
+-void LLPerfStats::openPerfStatsFile()
+-{
+- if ( !mFrameStatsFile
+- && !mFrameStatsFileFailure )
+- {
+- std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID);
+- mFrameStatsFile.close();
+- mFrameStatsFile.clear();
+- mFrameStatsFile.open(stats_file, llofstream::out);
+- if ( mFrameStatsFile.fail() )
+- {
+- llinfos << "Error opening statistics log file " << stats_file << llendl;
+- mFrameStatsFileFailure = TRUE;
+- }
+- else
+- {
+- LLSD process_info = LLSD::emptyMap();
+- process_info["name"] = mProcessName;
+- process_info["pid"] = (LLSD::Integer) mProcessPID;
+- process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval;
+- // Add process-specific info.
+- addProcessHeaderInfo(process_info);
+-
+- mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl;
+- }
+- }
+-}
+-
+-// Dump out performance metrics over some time interval
+-void LLPerfStats::dumpIntervalPerformanceStats()
+-{
+- // Ensure output file is OK
+- openPerfStatsFile();
+-
+- if ( mFrameStatsFile )
+- {
+- LLSD stats = LLSD::emptyMap();
+-
+- LLStatAccum::TimeScale scale;
+- if ( getReportPerformanceInterval() == 0.f )
+- {
+- scale = LLStatAccum::SCALE_PER_FRAME;
+- }
+- else if ( getReportPerformanceInterval() < 0.5f )
+- {
+- scale = LLStatAccum::SCALE_100MS;
+- }
+- else
+- {
+- scale = LLStatAccum::SCALE_SECOND;
+- }
+-
+- // Write LLSD into log
+- stats["utc_time"] = (LLSD::String) LLError::utcTime();
+- stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch
+- stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount();
+-
+- // Add process-specific frame info.
+- addProcessFrameInfo(stats, scale);
+- LLPerfBlock::addStatsToLLSDandReset( stats, scale );
+-
+- mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl;
+- }
+-}
+-
+-// Set length of performance stat recording
+-void LLPerfStats::setReportPerformanceDuration( F32 seconds )
+-{
+- if ( seconds <= 0.f )
+- {
+- mReportPerformanceStatEnd = 0.0;
+- LLPerfBlock::setStatsEnabled( FALSE );
+- mFrameStatsFile.close();
+- LLPerfBlock::clearDynamicStats();
+- }
+- else
+- {
+- mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
+- // Clear failure flag to try and create the log file once
+- mFrameStatsFileFailure = FALSE;
+- LLPerfBlock::setStatsEnabled( TRUE );
+- mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
+- }
+-}
+-
+-void LLPerfStats::updatePerFrameStats()
+-{
+- (void) LLStatsConfigFile::instance().checkAndReload();
+- static LLFrameTimer performance_stats_timer;
+- if ( frameStatsIsRunning() )
+- {
+- if ( mReportPerformanceStatInterval == 0 )
+- { // Record info every frame
+- if ( mSkipFirstFrameStats )
+- { // Skip the first time - was started this frame
+- mSkipFirstFrameStats = FALSE;
+- }
+- else
+- {
+- dumpIntervalPerformanceStats();
+- }
+- }
+- else
+- {
+- performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() );
+- if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval ))
+- {
+- dumpIntervalPerformanceStats();
+- }
+- }
+-
+- if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd )
+- { // Reached end of time, clear it to stop reporting
+- setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly
+- llinfos << "Recording performance stats completed" << llendl;
+- }
+- }
+-}
+-
+-
+-//------------------------------------------------------------------------
+-
+-U64 LLStatAccum::sScaleTimes[NUM_SCALES] =
++U64 LLStatAccum::sScaleTimes[IMPL_NUM_SCALES] =
+ {
+ USEC_PER_SEC / 10, // 100 millisec
+ USEC_PER_SEC * 1, // seconds
+ USEC_PER_SEC * 60, // minutes
++ USEC_PER_SEC * 60 * 2 // two minutes
+ #if ENABLE_LONG_TIME_STATS
+ // enable these when more time scales are desired
+ USEC_PER_SEC * 60*60, // hours
+@@ -342,7 +71,7 @@ void LLStatAccum::reset(U64 when)
+ mRunning = TRUE;
+ mLastTime = when;
+
+- for (int i = 0; i < NUM_SCALES; ++i)
++ for (int i = 0; i < IMPL_NUM_SCALES; ++i)
+ {
+ mBuckets[i].accum = 0.0;
+ mBuckets[i].endTime = when + sScaleTimes[i];
+@@ -375,7 +104,7 @@ void LLStatAccum::sum(F64 value, U64 when)
+ // how long is this value for
+ U64 timeSpan = when - mLastTime;
+
+- for (int i = 0; i < NUM_SCALES; ++i)
++ for (int i = 0; i < IMPL_NUM_SCALES; ++i)
+ {
+ Bucket& bucket = mBuckets[i];
+
+@@ -421,12 +150,7 @@ F32 LLStatAccum::meanValue(TimeScale scale) const
+ {
+ return 0.0;
+ }
+- if ( scale == SCALE_PER_FRAME )
+- { // Per-frame not supported here
+- scale = SCALE_100MS;
+- }
+-
+- if (scale < 0 || scale >= NUM_SCALES)
++ if (scale < 0 || scale >= IMPL_NUM_SCALES)
+ {
+ llwarns << "llStatAccum::meanValue called for unsupported scale: "
+ << scale << llendl;
+@@ -536,15 +260,12 @@ void LLStatMeasure::sample(F64 value)
+
+ // ------------------------------------------------------------------------
+
+-LLStatTime::LLStatTime(const std::string & key)
+- : LLStatAccum(false),
+- mFrameNumber(LLFrameTimer::getFrameCount()),
+- mTotalTimeInFrame(0),
+- mKey(key)
+-#if LL_DEBUG
+- , mRunning(FALSE)
+-#endif
++LLStatTime::LLStatTime(bool use_frame_timer)
++ : LLStatAccum(use_frame_timer),
++ mFrameNumber(0),
++ mTotalTimeInFrame(0)
+ {
++ mFrameNumber = LLFrameTimer::getFrameCount();
+ }
+
+ void LLStatTime::start()
+@@ -558,12 +279,6 @@ void LLStatTime::start()
+ }
+
+ sum(0.0);
+-
+-#if LL_DEBUG
+- // Shouldn't be running already
+- llassert( !mRunning );
+- mRunning = TRUE;
+-#endif
+ }
+
+ void LLStatTime::stop()
+@@ -571,149 +286,7 @@ void LLStatTime::stop()
+ U64 end_time = getCurrentUsecs();
+ U64 duration = end_time - mLastTime;
+ sum(F64(duration), end_time);
+- //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl;
+ mTotalTimeInFrame += duration;
+-
+-#if LL_DEBUG
+- mRunning = FALSE;
+-#endif
+-}
+-
+-/* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const
+-{
+- if ( LLStatAccum::SCALE_PER_FRAME == scale )
+- {
+- return mTotalTimeInFrame;
+- }
+- else
+- {
+- return LLStatAccum::meanValue(scale);
+- }
+-}
+-
+-
+-// ------------------------------------------------------------------------
+-
+-
+-// Use this constructor for pre-defined LLStatTime objects
+-LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL)
+-{
+- if (mPredefinedStat)
+- {
+- // If dynamic stats are turned on, this will create a separate entry in the stat map.
+- initDynamicStat(mPredefinedStat->mKey);
+-
+- // Start predefined stats. These stats are not part of the stat map.
+- mPredefinedStat->start();
+- }
+-}
+-
+-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
+-// These are also turned on or off via the switch passed in
+-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+-{
+- if (!sStatsEnabled) return;
+-
+- if (NULL == key2 || strlen(key2) == 0)
+- {
+- initDynamicStat(key1);
+- }
+- else
+- {
+- std::ostringstream key;
+- key << key1 << "_" << key2;
+- initDynamicStat(key.str());
+- }
+-}
+-
+-void LLPerfBlock::initDynamicStat(const std::string& key)
+-{
+- // Early exit if dynamic stats aren't enabled.
+- if (!sStatsEnabled) return;
+-
+- mLastPath = sCurrentStatPath; // Save and restore current path
+- sCurrentStatPath += "/" + key; // Add key to current path
+-
+- // See if the LLStatTime object already exists
+- stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath);
+- if ( iter == sStatMap.end() )
+- {
+- // StatEntry object doesn't exist, so create it
+- mDynamicStat = new StatEntry( key );
+- sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path
+- }
+- else
+- {
+- // Found this path in the map, use the object there
+- mDynamicStat = (*iter).second; // Get StatEntry for the current path
+- }
+-
+- if (mDynamicStat)
+- {
+- mDynamicStat->mStat.start();
+- mDynamicStat->mCount++;
+- }
+- else
+- {
+- llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl;
+- sCurrentStatPath = mLastPath;
+- }
+-}
+-
+-
+-// Destructor does the time accounting
+-LLPerfBlock::~LLPerfBlock()
+-{
+- if (mPredefinedStat) mPredefinedStat->stop();
+- if (mDynamicStat)
+- {
+- mDynamicStat->mStat.stop();
+- sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block
+- }
+-}
+-
+-
+-// Clear the map of any dynamic stats. Static routine
+-void LLPerfBlock::clearDynamicStats()
+-{
+- std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer());
+- sStatMap.clear();
+-}
+-
+-// static - Extract the stat info into LLSD
+-void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
+- LLStatAccum::TimeScale scale )
+-{
+- // If we aren't in per-frame scale, we need to go from second to microsecond.
+- U32 scale_adjustment = 1;
+- if (LLStatAccum::SCALE_PER_FRAME != scale)
+- {
+- scale_adjustment = USEC_PER_SEC;
+- }
+- stat_map_t::iterator iter = sStatMap.begin();
+- for ( ; iter != sStatMap.end(); ++iter )
+- { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time
+- const std::string & stats_full_path = (*iter).first;
+-
+- StatEntry * stat = (*iter).second;
+- if (stat)
+- {
+- if (stat->mCount > 0)
+- {
+- stats[stats_full_path] = LLSD::emptyMap();
+- stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale));
+- if (stat->mCount > 1)
+- {
+- stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount;
+- }
+- stat->mCount = 0;
+- }
+- }
+- else
+- { // WTF? Shouldn't have a NULL pointer in the map.
+- llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
+- }
+- }
+ }
+
+
+diff --git a/linden/indra/llcommon/llstat.h b/linden/indra/llcommon/llstat.h
+index eceb5e3..0e66cf0 100644
+--- a/linden/indra/llcommon/llstat.h
++++ b/linden/indra/llcommon/llstat.h
+@@ -33,13 +33,9 @@
+ #define LL_LLSTAT_H
+
+ #include
+-#include
+
+ #include "lltimer.h"
+ #include "llframetimer.h"
+-#include "llfile.h"
+-
+-class LLSD;
+
+ // Set this if longer stats are needed
+ #define ENABLE_LONG_TIME_STATS 0
+@@ -62,18 +58,19 @@ public:
+ SCALE_100MS,
+ SCALE_SECOND,
+ SCALE_MINUTE,
++ SCALE_TWO_MINUTE,
+ #if ENABLE_LONG_TIME_STATS
+ SCALE_HOUR,
+ SCALE_DAY,
+ SCALE_WEEK,
+ #endif
+- NUM_SCALES, // Use to size storage arrays
+- SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets
++ NUM_SCALES
+ };
+
+- static U64 sScaleTimes[NUM_SCALES];
++ static const TimeScale IMPL_NUM_SCALES = (TimeScale)(SCALE_TWO_MINUTE + 1);
++ static U64 sScaleTimes[IMPL_NUM_SCALES];
+
+- virtual F32 meanValue(TimeScale scale) const;
++ F32 meanValue(TimeScale scale) const;
+ // see the subclasses for the specific meaning of value
+
+ F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); }
+@@ -89,8 +86,8 @@ public:
+ // Get current microseconds based on timer type
+
+ BOOL mUseFrameTimer;
+- BOOL mRunning;
+
++ BOOL mRunning;
+ U64 mLastTime;
+
+ struct Bucket
+@@ -102,7 +99,7 @@ public:
+ F64 lastAccum;
+ };
+
+- Bucket mBuckets[NUM_SCALES];
++ Bucket mBuckets[IMPL_NUM_SCALES];
+
+ BOOL mLastSampleValid;
+ F64 mLastSampleValue;
+@@ -139,115 +136,37 @@ public:
+ };
+
+
++class LLTimeBlock;
++
+ class LLStatTime : public LLStatAccum
+ // gathers statistics about time spent in a block of code
+ // measure average duration per second in the block
+ {
+ public:
+- LLStatTime( const std::string & key = "undefined" );
++ LLStatTime(bool use_frame_timer = false);
+
+ U32 mFrameNumber; // Current frame number
+ U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame
+
+- void setKey( const std::string & key ) { mKey = key; };
+-
+- virtual F32 meanValue(TimeScale scale) const;
+-
+ private:
+- void start(); // Start and stop measuring time block
++ void start();
+ void stop();
+-
+- std::string mKey; // Tag representing this time block
+-
+-#if LL_DEBUG
+- BOOL mRunning; // TRUE if start() has been called
+-#endif
+-
+- friend class LLPerfBlock;
++ friend class LLTimeBlock;
+ };
+
+-// ----------------------------------------------------------------------------
+-
+-
+-// Use this class on the stack to record statistics about an area of code
+-class LLPerfBlock
++class LLTimeBlock
+ {
+ public:
+- struct StatEntry
+- {
+- StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {}
+- LLStatTime mStat;
+- U32 mCount;
+- };
+- typedef std::map stat_map_t;
+-
+- // Use this constructor for pre-defined LLStatTime objects
+- LLPerfBlock(LLStatTime* stat);
+-
+- // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
+- LLPerfBlock( const char* key1, const char* key2 = NULL);
+-
+-
+- ~LLPerfBlock();
+-
+- static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; };
+- static S32 getStatsEnabled() { return sStatsEnabled; };
+-
+- static void clearDynamicStats(); // Reset maps to clear out dynamic objects
+- static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin
+- LLStatAccum::TimeScale scale );
+-
++ LLTimeBlock(LLStatTime& stat) : mStat(stat) { mStat.start(); }
++ ~LLTimeBlock() { mStat.stop(); }
+ private:
+- // Initialize dynamically created LLStatTime objects
+- void initDynamicStat(const std::string& key);
+-
+- std::string mLastPath; // Save sCurrentStatPath when this is called
+- LLStatTime * mPredefinedStat; // LLStatTime object to get data
+- StatEntry * mDynamicStat; // StatEntryobject to get data
+-
+- static BOOL sStatsEnabled; // Normally FALSE
+- static stat_map_t sStatMap; // Map full path string to LLStatTime objects
+- static std::string sCurrentStatPath; // Something like "frame/physics/physics step"
++ LLStatTime& mStat;
+ };
+
+-// ----------------------------------------------------------------------------
+
+-class LLPerfStats
+-{
+-public:
+- LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
+- virtual ~LLPerfStats();
+-
+- virtual void init(); // Reset and start all stat timers
+- virtual void updatePerFrameStats();
+- // Override these function to add process-specific information to the performance log header and per-frame logging.
+- virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ }
+- virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ }
+-
+- // High-resolution frame stats
+- BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); };
+- F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; };
+- void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; };
+- void setReportPerformanceDuration( F32 seconds );
+- void setProcessName(const std::string& process_name) { mProcessName = process_name; }
+- void setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
+-
+-protected:
+- void openPerfStatsFile(); // Open file for high resolution metrics logging
+- void dumpIntervalPerformanceStats();
+
+- llofstream mFrameStatsFile; // File for per-frame stats
+- BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts
+- BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report
+- std::string mProcessName;
+- S32 mProcessPID;
+
+-private:
+- F32 mReportPerformanceStatInterval; // Seconds between performance stats
+- F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats
+-};
+
+-// ----------------------------------------------------------------------------
+ class LLStat
+ {
+ public:
+diff --git a/linden/indra/llcommon/llstatenums.h b/linden/indra/llcommon/llstatenums.h
+index febd958..ae3be14 100644
+--- a/linden/indra/llcommon/llstatenums.h
++++ b/linden/indra/llcommon/llstatenums.h
+@@ -33,41 +33,38 @@
+
+ enum
+ {
+- LL_SIM_STAT_TIME_DILATION, // 0
++ LL_SIM_STAT_TIME_DILATION,
+ LL_SIM_STAT_FPS,
+ LL_SIM_STAT_PHYSFPS,
+ LL_SIM_STAT_AGENTUPS,
+ LL_SIM_STAT_FRAMEMS,
+- LL_SIM_STAT_NETMS, // 5
++ LL_SIM_STAT_NETMS,
+ LL_SIM_STAT_SIMOTHERMS,
+ LL_SIM_STAT_SIMPHYSICSMS,
+ LL_SIM_STAT_AGENTMS,
+ LL_SIM_STAT_IMAGESMS,
+- LL_SIM_STAT_SCRIPTMS, // 10
++ LL_SIM_STAT_SCRIPTMS,
+ LL_SIM_STAT_NUMTASKS,
+ LL_SIM_STAT_NUMTASKSACTIVE,
+ LL_SIM_STAT_NUMAGENTMAIN,
+ LL_SIM_STAT_NUMAGENTCHILD,
+- LL_SIM_STAT_NUMSCRIPTSACTIVE, // 15
++ LL_SIM_STAT_NUMSCRIPTSACTIVE,
+ LL_SIM_STAT_LSLIPS,
+ LL_SIM_STAT_INPPS,
+ LL_SIM_STAT_OUTPPS,
+ LL_SIM_STAT_PENDING_DOWNLOADS,
+- LL_SIM_STAT_PENDING_UPLOADS, // 20
++ LL_SIM_STAT_PENDING_UPLOADS,
+ LL_SIM_STAT_VIRTUAL_SIZE_KB,
+ LL_SIM_STAT_RESIDENT_SIZE_KB,
+ LL_SIM_STAT_PENDING_LOCAL_UPLOADS,
+ LL_SIM_STAT_TOTAL_UNACKED_BYTES,
+- LL_SIM_STAT_PHYSICS_PINNED_TASKS, // 25
++ LL_SIM_STAT_PHYSICS_PINNED_TASKS,
+ LL_SIM_STAT_PHYSICS_LOD_TASKS,
+ LL_SIM_STAT_SIMPHYSICSSTEPMS,
+ LL_SIM_STAT_SIMPHYSICSSHAPEMS,
+ LL_SIM_STAT_SIMPHYSICSOTHERMS,
+- LL_SIM_STAT_SIMPHYSICSMEMORY, // 30
++ LL_SIM_STAT_SIMPHYSICSMEMORY,
+ LL_SIM_STAT_SCRIPT_EPS,
+- LL_SIM_STAT_SIMSPARETIME,
+- LL_SIM_STAT_SIMSLEEPTIME,
+- LL_SIM_STAT_IOPUMPTIME,
+ };
+
+ #endif
+diff --git a/linden/indra/llmessage/lliohttpserver.cpp b/linden/indra/llmessage/lliohttpserver.cpp
+index 167f212..39fecb4 100644
+--- a/linden/indra/llmessage/lliohttpserver.cpp
++++ b/linden/indra/llmessage/lliohttpserver.cpp
+@@ -47,7 +47,6 @@
+ #include "llpumpio.h"
+ #include "llsd.h"
+ #include "llsdserialize_xml.h"
+-#include "llstat.h"
+ #include "llstl.h"
+ #include "lltimer.h"
+
+@@ -172,26 +171,22 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
+ std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
+ if(verb == HTTP_VERB_GET)
+ {
+- LLPerfBlock getblock("http_get");
+ mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else if(verb == HTTP_VERB_PUT)
+ {
+- LLPerfBlock putblock("http_put");
+ LLSD input;
+ LLSDSerialize::fromXML(input, istr);
+ mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
+ }
+ else if(verb == HTTP_VERB_POST)
+ {
+- LLPerfBlock postblock("http_post");
+ LLSD input;
+ LLSDSerialize::fromXML(input, istr);
+ mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
+ }
+ else if(verb == HTTP_VERB_DELETE)
+ {
+- LLPerfBlock delblock("http_delete");
+ mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else if(verb == HTTP_VERB_OPTIONS)
+diff --git a/linden/indra/llmessage/llmessagetemplate.h b/linden/indra/llmessage/llmessagetemplate.h
+index 2390eea..a4062fa 100644
+--- a/linden/indra/llmessage/llmessagetemplate.h
++++ b/linden/indra/llmessage/llmessagetemplate.h
+@@ -34,8 +34,11 @@
+
+ #include "lldarray.h"
+ #include "message.h" // TODO: babbage: Remove...
+-#include "llstat.h"
++#include "llmsgvariabletype.h"
+ #include "llstl.h"
++#include
++#include
++#include
+
+ class LLMsgVarData
+ {
+@@ -270,6 +273,31 @@ enum EMsgDeprecation
+ MD_DEPRECATED
+ };
+
++class LLMessageTemplateHandlerEntry
++{
++public:
++ LLMessageTemplateHandlerEntry(message_handler_func_t handler, void **userdata = NULL) :
++ mHandlerFunc(handler), mUserData(userdata) {}
++
++ void call(LLMessageSystem *msgsystem) const { mHandlerFunc(msgsystem, mUserData); }
++
++ bool operator==(const LLMessageTemplateHandlerEntry&a) { return mHandlerFunc == a.mHandlerFunc; }
++private:
++ // message handler function (this is set by each application)
++ message_handler_func_t mHandlerFunc;
++ void **mUserData;
++};
++
++class callHandler : public std::unary_function
++{
++public:
++ callHandler(LLMessageSystem *msg) : mMsg(msg) {}
++ void operator()(const LLMessageTemplateHandlerEntry& a) const { a.call(mMsg); }
++private:
++ LLMessageSystem *mMsg;
++};
++
++
+ class LLMessageTemplate
+ {
+ public:
+@@ -291,9 +319,10 @@ public:
+ mTotalDecodeTime(0.f),
+ mMaxDecodeTimePerMsg(0.f),
+ mBanFromTrusted(false),
+- mBanFromUntrusted(false),
+- mHandlerFunc(NULL),
+- mUserData(NULL)
++ //mBanFromUntrusted(false),
++ //mHandlerFunc(NULL),
++ //mUserData(NULL)
++ mBanFromUntrusted(false)
+ {
+ mName = LLMessageStringTable::getInstance()->getString(name);
+ }
+@@ -361,21 +390,91 @@ public:
+ return mDeprecation;
+ }
+
+- void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
++// void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
++ /**
++ * @brief Adds a handler
++ * This function adds a new handler to be called when the message arrives.
++ * Repeated additions of the same handler function will be ignored.
++ * @note delHandlerFunc() must be called to remove the registration
++ * @param handler Function to call
++ * @param user_data User specified data to pass to the function
++ */
++ void addHandlerFunc(message_handler_func_t handler, void **user_data)
+ {
+- mHandlerFunc = handler_func;
+- mUserData = user_data;
++ LLMessageTemplateHandlerEntry h(handler, user_data);
++
++ if ( std::find(mHandlers.begin(), mHandlers.end(), h ) != mHandlers.end() )
++ {
++ return;
++ }
++
++ mHandlers.push_back( h );
++ }
++
++ /**
++ * @brief Sets a handler
++ * This function sets a handler to be called when the message arrives.
++ * Any existing handlers are unregistered.
++ * @note delHandlerFunc() must be called to remove the registration
++ * @param handler Function to call
++ * @param user_data User specified data to pass to the function
++ */
++ void setHandlerFunc(message_handler_func_t handler, void **user_data)
++ {
++ mHandlers.clear();
++ if( handler )
++ {
++ addHandlerFunc(handler, user_data);
++ }
++ else
++ {
++ llwarns << "code has reset handler for \"" << mName << "\" by setting it to NULL." << llendl;
++ }
++ }
++
++ /**
++ * @brief Removes a handler
++ * Removes a handler from the list of handlers.
++ * Attempts to remove handlers that aren't in the list are silently
++ * ignored.
++ * @param handler Function to remove
++ */
++ void delHandlerFunc(message_handler_func_t handler)
++ {
++ //mHandlerFunc = handler_func;
++ //mUserData = user_data;
++ mHandlers.remove( LLMessageTemplateHandlerEntry(handler) );
+ }
+
+ BOOL callHandlerFunc(LLMessageSystem *msgsystem) const
+ {
+- if (mHandlerFunc)
++ //if (mHandlerFunc)
++ if ( mHandlers.empty() )
++ {
++ return FALSE;
++ }
++ /*
++ * Be on the safe side and use for_each only when necessary. There is Linden code ("ReplyPayPrice") that
++ * does not take the multiple reply handlers into account and simply tries to unregister
++ * by setting the handler function to 0, unfortunately from within the reply handler so in this case
++ * the for_each iterator inside std_algo.h is invalidated leading to a crash if the memory is reused
++ * in between.
++ */
++ else if( mHandlers.size() == 1 )
++ {
++ //KOW HACK we probably want to re-enable the llPerfBlocks here, may need a vendor merge for llstats.cpp stuff.
++ //LLPerfBlock msg_cb_time("msg_cb", mName);
++ //mHandlerFunc(msgsystem, mUserData);
++ mHandlers.begin()->call(msgsystem);
++ return TRUE;
++ }
++ else
+ {
+- LLPerfBlock msg_cb_time("msg_cb", mName);
+- mHandlerFunc(msgsystem, mUserData);
++ //LLPerfBlock msg_cb_time("msg_cb", mName);
++ std::for_each(mHandlers.begin(), mHandlers.end(), callHandler(msgsystem));
+ return TRUE;
+ }
+- return FALSE;
++ //return FALSE;
+ }
+
+ bool isUdpBanned() const
+@@ -421,8 +520,9 @@ public:
+
+ private:
+ // message handler function (this is set by each application)
+- void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
+- void **mUserData;
++// void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
++// void **mUserData;
++ std::list mHandlers;
+ };
+
+ #endif // LL_LLMESSAGETEMPLATE_H
+diff --git a/linden/indra/llmessage/llpumpio.cpp b/linden/indra/llmessage/llpumpio.cpp
+index 01a43ec..cc9e543 100644
+--- a/linden/indra/llmessage/llpumpio.cpp
++++ b/linden/indra/llmessage/llpumpio.cpp
+@@ -41,7 +41,6 @@
+ #include "llapr.h"
+ #include "llmemtype.h"
+ #include "llstl.h"
+-#include "llstat.h"
+
+ // These should not be enabled in production, but they can be
+ // intensely useful during development for finding certain kinds of
+@@ -177,8 +176,7 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) :
+ mCurrentPool(NULL),
+ mCurrentPoolReallocCount(0),
+ mChainsMutex(NULL),
+- mCallbackMutex(NULL),
+- mCurrentChain(mRunningChains.end())
++ mCallbackMutex(NULL)
+ {
+ LLMemType m1(LLMemType::MTYPE_IO_PUMP);
+ initialize(pool);
+@@ -274,10 +272,7 @@ bool LLPumpIO::setTimeoutSeconds(F32 timeout)
+ void LLPumpIO::adjustTimeoutSeconds(F32 delta)
+ {
+ // If no chain is running, bail
+- if(mRunningChains.end() == mCurrentChain)
+- {
+- return;
+- }
++ if(current_chain_t() == mCurrentChain) return;
+ (*mCurrentChain).adjustTimeoutSeconds(delta);
+ }
+
+@@ -526,10 +521,7 @@ void LLPumpIO::pump(const S32& poll_timeout)
+ //llinfos << "polling" << llendl;
+ S32 count = 0;
+ S32 client_id = 0;
+- {
+- LLPerfBlock polltime("pump_poll");
+ apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
+- }
+ PUMP_DEBUG;
+ for(S32 ii = 0; ii < count; ++ii)
+ {
+diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp
+index ccc3d79..0d0ad18 100644
+--- a/linden/indra/llmessage/message.cpp
++++ b/linden/indra/llmessage/message.cpp
+@@ -754,7 +754,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
+ clearReceiveState();
+ valid_packet = FALSE;
+ }
+-
+ if( valid_packet && mTemplateMessageReader->isUdpBanned())
+ {
+ llwarns << "Received UDP black listed message "
+@@ -767,6 +766,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
+ if( valid_packet )
+ {
+ logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
++
+ valid_packet = mTemplateMessageReader->readMessage(buffer, host);
+ }
+
+@@ -2972,7 +2972,7 @@ void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
+ }
+
+
+-void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
++void LLMessageSystem::setHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
+ {
+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
+ if (msgtemplate)
+@@ -2985,6 +2985,32 @@ void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(
+ }
+ }
+
++void LLMessageSystem::addHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
++{
++ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
++ if (msgtemplate)
++ {
++ msgtemplate->addHandlerFunc(handler_func, user_data);
++ }
++ else
++ {
++ llerrs << name << " is not a known message name!" << llendl;
++ }
++}
++
++void LLMessageSystem::delHandlerFuncFast(const char *name, message_handler_func_t handler_func)
++{
++ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
++ if (msgtemplate)
++ {
++ msgtemplate->delHandlerFunc(handler_func);
++ }
++ else
++ {
++ llerrs << name << " is not a known message name!" << llendl;
++ }
++}
++
+ bool LLMessageSystem::callHandler(const char *name,
+ bool trustedSource, LLMessageSystem* msg)
+ {
+@@ -3956,27 +3982,27 @@ void LLMessageSystem::getString(const char *block, const char *var,
+ blocknum);
+ }
+
+-BOOL LLMessageSystem::has(const char *blockname) const
++BOOL LLMessageSystem::has(const char *blockname)
+ {
+ return getNumberOfBlocks(blockname) > 0;
+ }
+
+-S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
++S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname)
+ {
+ return mMessageReader->getNumberOfBlocks(blockname);
+ }
+
+-S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
++S32 LLMessageSystem::getNumberOfBlocks(const char *blockname)
+ {
+ return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
+ }
+
+-S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
++S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname)
+ {
+ return mMessageReader->getSize(blockname, varname);
+ }
+
+-S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
++S32 LLMessageSystem::getSize(const char *blockname, const char *varname)
+ {
+ return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
+ LLMessageStringTable::getInstance()->getString(varname));
+@@ -3984,13 +4010,13 @@ S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
+
+ // size in bytes of variable length data
+ S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
+- const char *varname) const
++ const char *varname)
+ {
+ return mMessageReader->getSize(blockname, blocknum, varname);
+ }
+
+ S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
+- const char *varname) const
++ const char *varname)
+ {
+ return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
+ LLMessageStringTable::getInstance()->getString(varname));
+diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h
+index c503a58..4b96526 100644
+--- a/linden/indra/llmessage/message.h
++++ b/linden/indra/llmessage/message.h
+@@ -179,7 +179,7 @@ enum EMessageException
+ MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
+ };
+ typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
+-
++typedef void (*message_handler_func_t)(LLMessageSystem *msgsystem, void **user_data);
+
+ // message data pieces are used to collect the data called for by the message template
+ class LLMsgData;
+@@ -299,12 +299,24 @@ public:
+
+
+ // methods for building, sending, receiving, and handling messages
+- void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
+- void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
++ void setHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
++ void setHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
+ {
+ setHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
+ }
+
++ void addHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
++ void addHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
++ {
++ addHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
++ }
++
++ void delHandlerFuncFast(const char *name, message_handler_func_t);
++ void delHandlerFunc(const char *name, message_handler_func_t handler_func)
++ {
++ delHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func);
++ }
++
+ // Set a callback function for a message system exception.
+ void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
+ // Call the specified exception func, and return TRUE if a
+@@ -594,14 +606,14 @@ public:
+ LLHost findHost(const U32 circuit_code);
+ void sanityCheck();
+
+- BOOL has(const char *blockname) const;
+- S32 getNumberOfBlocksFast(const char *blockname) const;
+- S32 getNumberOfBlocks(const char *blockname) const;
+- S32 getSizeFast(const char *blockname, const char *varname) const;
+- S32 getSize(const char *blockname, const char *varname) const;
++ BOOL has(const char *blockname);
++ S32 getNumberOfBlocksFast(const char *blockname);
++ S32 getNumberOfBlocks(const char *blockname);
++ S32 getSizeFast(const char *blockname, const char *varname);
++ S32 getSize(const char *blockname, const char *varname);
+ S32 getSizeFast(const char *blockname, S32 blocknum,
+- const char *varname) const; // size in bytes of data
+- S32 getSize(const char *blockname, S32 blocknum, const char *varname) const;
++ const char *varname); // size in bytes of data
++ S32 getSize(const char *blockname, S32 blocknum, const char *varname);
+
+ void resetReceiveCounts(); // resets receive counts for all message types to 0
+ void dumpReceiveCounts(); // dumps receive count for each message type to llinfos
+diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
+index cf9a7cd..4927571 100644
+--- a/linden/indra/newview/app_settings/settings.xml
++++ b/linden/indra/newview/app_settings/settings.xml
+@@ -4762,7 +4762,7 @@
+ Type
+ U32
+ Value
+- 0
++ 1
+
+ MemoryLogFrequency
+
+diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
+index cab9815..5cd2a56 100644
+--- a/linden/indra/newview/llstartup.cpp
++++ b/linden/indra/newview/llstartup.cpp
+@@ -3152,7 +3152,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
+ msg->setHandlerFunc("ParcelDwellReply",
+ LLViewerParcelMgr::processParcelDwellReply);
+
+- msg->setHandlerFunc("AvatarPropertiesReply",
++ msg->addHandlerFunc("AvatarPropertiesReply",
+ LLPanelAvatar::processAvatarPropertiesReply);
+ msg->setHandlerFunc("AvatarInterestsReply",
+ LLPanelAvatar::processAvatarInterestsReply);
+diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
+index 03114f7..b984687 100644
+--- a/linden/indra/newview/llviewermessage.cpp
++++ b/linden/indra/newview/llviewermessage.cpp
+@@ -3516,15 +3516,6 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
+ case LL_SIM_STAT_SIMPHYSICSMEMORY:
+ LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value);
+ break;
+- case LL_SIM_STAT_SIMSPARETIME:
+- LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value);
+- break;
+- case LL_SIM_STAT_SIMSLEEPTIME:
+- LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value);
+- break;
+- case LL_SIM_STAT_IOPUMPTIME:
+- LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value);
+- break;
+ default:
+ // Used to be a commented out warning.
+ LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL;
+diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h
+index dc529cd..ebb46b9 100644
+--- a/linden/indra/newview/llviewerobject.h
++++ b/linden/indra/newview/llviewerobject.h
+@@ -600,7 +600,9 @@ protected:
+ // extra data sent from the sim...currently only used for tree species info
+ U8* mData;
+
++public:
+ LLPointer mPartSourcep; // Particle source associated with this object.
++protected:
+ LLAudioSourceVO* mAudioSourcep;
+ F32 mAudioGain;
+
+diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp
+index 3d2523e..86993df 100644
+--- a/linden/indra/newview/llvoavatar.cpp
++++ b/linden/indra/newview/llvoavatar.cpp
+@@ -891,7 +891,6 @@ LLVOAvatar::LLVOAvatar(
+ mEyeBallLeftMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+ mEyeBallRightMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+ mEyeBallRightMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+-
+ //-------------------------------------------------------------------------
+ // register motions
+ //-------------------------------------------------------------------------
+@@ -960,7 +959,8 @@ LLVOAvatar::LLVOAvatar(
+ //VTPause(); // VTune
+
+ mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
+- mCurrentGesticulationLevel = 0;
++ mCurrentGesticulationLevel = 0;
++
+ }
+
+ //------------------------------------------------------------------------
+@@ -1990,7 +1990,8 @@ void LLVOAvatar::buildCharacter()
+ mWristRightp = (LLViewerJoint*)mRoot.findJoint("mWristRight");
+ mEyeLeftp = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
+ mEyeRightp = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
+-
++
++ lldebugs << " initialized joint pointers" << llendl;
+ //-------------------------------------------------------------------------
+ // Make sure "well known" pointers exist
+ //-------------------------------------------------------------------------
+@@ -2016,7 +2017,7 @@ void LLVOAvatar::buildCharacter()
+ llerrs << "Failed to create avatar." << llendl;
+ return;
+ }
+-
++ lldebugs << "pointers exist, good." << llendl;
+ //-------------------------------------------------------------------------
+ // initialize the pelvis
+ //-------------------------------------------------------------------------
+@@ -2140,7 +2141,7 @@ void LLVOAvatar::buildCharacter()
+ }
+ }
+ }
+-
++ lldebugs << "builded the attach and detach menus" << llendl;
+ // add screen attachments
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end(); )
+@@ -2159,6 +2160,7 @@ void LLVOAvatar::buildCharacter()
+ &handle_detach_from_avatar, object_attached, attachment));
+ }
+ }
++ lldebugs << "added screen attachments" << llendl;
+
+ for (S32 pass = 0; pass < 2; pass++)
+ {
+@@ -2188,6 +2190,7 @@ void LLVOAvatar::buildCharacter()
+ gDetachSubMenu->appendSeparator();
+ }
+ }
++ lldebugs << "added other attachments" << llendl;
+
+ for (S32 group = 0; group < 8; group++)
+ {
+@@ -2241,9 +2244,11 @@ void LLVOAvatar::buildCharacter()
+ }
+ }
+ }
++ lldebugs << "added pies" << llendl;
+ }
+
+ mMeshValid = TRUE;
++ lldebugs << "mMeshValid = TRUE" << llendl;
+ }
+
+
diff --git a/meerkat-pipeline.cpp.diff.txt b/meerkat-pipeline.cpp.diff.txt
new file mode 100644
index 0000000..b34cd94
--- /dev/null
+++ b/meerkat-pipeline.cpp.diff.txt
@@ -0,0 +1,22 @@
+--- /linden/indra/newview/pipeline.cpp 2009-06-25 15:23:44.000000000 +0200
++++ /linden/indra/newview/pipeline.cpp 2009-06-25 23:49:51.000000000 +0200
+@@ -2691,7 +2711,10 @@
+ // from Medium -> Low, because we unload all the shaders and the
+ // draw pools aren't aware. I don't know if this has to be a separate
+ // loop before actual rendering. JC
+- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
++
++ // TODO: this is a useful fix, find out why it breaks logout -- RMS
++
++/* for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (poolp->isFacePool() && hasRenderType(poolp->getType()))
+@@ -2699,6 +2722,7 @@
+ poolp->prerender();
+ }
+ }
++*/
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
diff --git a/meerkat-voice.diff.txt b/meerkat-voice.diff.txt
new file mode 100644
index 0000000..f49d511
--- /dev/null
+++ b/meerkat-voice.diff.txt
@@ -0,0 +1,7282 @@
+diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp
+index bf1f678..41137b4 100644
+--- a/linden/indra/newview/llfloaterfriends.cpp
++++ b/linden/indra/newview/llfloaterfriends.cpp
+@@ -57,7 +57,6 @@
+ #include "llviewermessage.h"
+ #include "lltimer.h"
+ #include "lltextbox.h"
+-#include "llvoiceclient.h"
+
+ //Maximum number of people you can select to do an operation on at once.
+ #define MAX_FRIEND_SELECT 20
+@@ -65,8 +64,6 @@
+ #define RIGHTS_CHANGE_TIMEOUT 5.0
+ #define OBSERVER_TIMEOUT 0.5
+
+-#define ONLINE_SIP_ICON_NAME "slim_icon_16_viewer.tga"
+-
+ // simple class to observe the calling cards.
+ class LLLocalFriendsObserver : public LLFriendObserver, public LLEventTimer
+ {
+@@ -114,14 +111,10 @@ LLPanelFriends::LLPanelFriends() :
+ mEventTimer.stop();
+ mObserver = new LLLocalFriendsObserver(this);
+ LLAvatarTracker::instance().addObserver(mObserver);
+- // For notification when SIP online status changes.
+- LLVoiceClient::getInstance()->addObserver(mObserver);
+ }
+
+ LLPanelFriends::~LLPanelFriends()
+ {
+- // For notification when SIP online status changes.
+- LLVoiceClient::getInstance()->removeObserver(mObserver);
+ LLAvatarTracker::instance().removeObserver(mObserver);
+ delete mObserver;
+ }
+@@ -219,9 +212,7 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ const LLRelationship* relationInfo = at.getBuddyInfo(agent_id);
+ if(!relationInfo) return FALSE;
+-
+- bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(agent_id);
+- bool isOnline = relationInfo->isOnline();
++ BOOL online = relationInfo->isOnline();
+
+ std::string fullname;
+ BOOL have_name = gCacheName->getFullName(agent_id, fullname);
+@@ -237,17 +228,12 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
+ LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS];
+ online_status_column["column"] = "icon_online_status";
+ online_status_column["type"] = "icon";
+-
+- if (isOnline)
++
++ if (online)
+ {
+ friend_column["font-style"] = "BOLD";
+ online_status_column["value"] = "icon_avatar_online.tga";
+ }
+- else if(isOnlineSIP)
+- {
+- friend_column["font-style"] = "BOLD";
+- online_status_column["value"] = ONLINE_SIP_ICON_NAME;
+- }
+
+ LLSD& online_column = element["columns"][LIST_VISIBLE_ONLINE];
+ online_column["column"] = "icon_visible_online";
+@@ -285,30 +271,14 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh
+ if (!info) return FALSE;
+ LLScrollListItem* itemp = mFriendsList->getItem(agent_id);
+ if (!itemp) return FALSE;
+-
+- bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(itemp->getUUID());
+- bool isOnline = info->isOnline();
+
+ std::string fullname;
+ BOOL have_name = gCacheName->getFullName(agent_id, fullname);
+-
+- // Name of the status icon to use
+- std::string statusIcon;
+-
+- if(isOnline)
+- {
+- statusIcon = "icon_avatar_online.tga";
+- }
+- else if(isOnlineSIP)
+- {
+- statusIcon = ONLINE_SIP_ICON_NAME;
+- }
+
+- itemp->getColumn(LIST_ONLINE_STATUS)->setValue(statusIcon);
+-
++ itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? std::string("icon_avatar_online.tga") : LLStringUtil::null);
+ itemp->getColumn(LIST_FRIEND_NAME)->setValue(fullname);
+ // render name of online friends in bold text
+- ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle((isOnline || isOnlineSIP) ? LLFontGL::BOLD : LLFontGL::NORMAL);
++ ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL);
+ itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
+ itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION));
+ itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS));
+diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp
+index f30ae8c..d3139ad 100644
+--- a/linden/indra/newview/llimpanel.cpp
++++ b/linden/indra/newview/llimpanel.cpp
+@@ -49,7 +49,6 @@
+ #include "llconsole.h"
+ #include "llfloater.h"
+ #include "llfloatergroupinfo.h"
+-#include "llfloaterchatterbox.h"
+ #include "llimview.h"
+ #include "llinventory.h"
+ #include "llinventorymodel.h"
+@@ -69,6 +68,7 @@
+ #include "lluictrlfactory.h"
+ #include "llviewerwindow.h"
+ #include "lllogchat.h"
++#include "llfloaterhtml.h"
+ #include "llweb.h"
+ #include "llhttpclient.h"
+ #include "llmutelist.h"
+@@ -357,7 +357,7 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess
+ llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
+ }
+
+- LLVoiceClient::getInstance()->addObserver(this);
++ LLVoiceClient::getInstance()->addStatusObserver(this);
+ }
+
+ LLVoiceChannel::~LLVoiceChannel()
+@@ -365,7 +365,7 @@ LLVoiceChannel::~LLVoiceChannel()
+ // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
+ if(gVoiceClient)
+ {
+- gVoiceClient->removeObserver(this);
++ gVoiceClient->removeStatusObserver(this);
+ }
+
+ sVoiceChannelMap.erase(mSessionID);
+@@ -983,8 +983,7 @@ void LLVoiceChannelP2P::activate()
+ // otherwise answering the call
+ else
+ {
+- LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
+-
++ LLVoiceClient::getInstance()->answerInvite(mSessionHandle, mOtherUserID);
+ // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
+ mSessionHandle.clear();
+ }
+@@ -1001,7 +1000,7 @@ void LLVoiceChannelP2P::getChannelInfo()
+ }
+
+ // receiving session from other user who initiated call
+-void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
++void LLVoiceChannelP2P::setSessionHandle(const std::string& handle)
+ {
+ BOOL needs_activate = FALSE;
+ if (callStarted())
+@@ -1024,17 +1023,8 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s
+ }
+
+ mSessionHandle = handle;
+-
+ // The URI of a p2p session should always be the other end's SIP URI.
+- if(!inURI.empty())
+- {
+- setURI(inURI);
+- }
+- else
+- {
+- setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
+- }
+-
++ setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
+ mReceivedCall = TRUE;
+
+ if (needs_activate)
+@@ -1171,7 +1161,6 @@ void LLFloaterIMPanel::init(const std::string& session_label)
+ FALSE);
+
+ setTitle(mSessionLabel);
+-
+ mInputEditor->setMaxTextLength(1023);
+ // enable line history support for instant message bar
+ mInputEditor->setEnableLineHistory(TRUE);
+@@ -1218,23 +1207,7 @@ LLFloaterIMPanel::~LLFloaterIMPanel()
+ {
+ delete mSpeakers;
+ mSpeakers = NULL;
+-
+- // End the text IM session if necessary
+- if(gVoiceClient && mOtherParticipantUUID.notNull())
+- {
+- switch(mDialog)
+- {
+- case IM_NOTHING_SPECIAL:
+- case IM_SESSION_P2P_INVITE:
+- gVoiceClient->endUserIMSession(mOtherParticipantUUID);
+- break;
+-
+- default:
+- // Appease the compiler
+- break;
+- }
+- }
+-
++
+ //kicks you out of the voice channel if it is currently active
+
+ // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
+@@ -1424,7 +1397,6 @@ void LLFloaterIMPanel::draw()
+ childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
+ childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
+ }
+-
+ LLFloater::draw();
+ }
+
+@@ -1505,7 +1477,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
+ if (!hostp->isFloaterFlashing(this))
+ {
+ hostp->setFloaterFlashing(this, TRUE);
+- LLFloaterChatterBox::markAsUnread(true);
++//awfixme LLFloaterChatterBox::markAsUnread(true);
+ }
+
+ //// Only increment the number of unread IMs if they're from individuals
+@@ -1585,7 +1557,7 @@ void LLFloaterIMPanel::setVisible(BOOL b)
+ if (hostp->isFloaterFlashing(this))
+ {
+ hostp->setFloaterFlashing(this, FALSE);
+- LLFloaterChatterBox::markAsUnread(false);
++//awfixme LLFloaterChatterBox::markAsUnread(false);
+
+ /* Don't change containing floater title - leave it "Instant Message" JC
+ LLUIString title = sTitleString;
+@@ -1926,46 +1898,34 @@ void deliver_message(const std::string& utf8_text,
+ EInstantMessage dialog)
+ {
+ std::string name;
+- bool sent = false;
+ gAgent.buildFullname(name);
+
+ const LLRelationship* info = NULL;
+ info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
+-
+ U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
+-
+- if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
+- {
+- // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
+- sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
+- }
+-
+- if(!sent)
+- {
+- // Send message normally.
+
+- // default to IM_SESSION_SEND unless it's nothing special - in
+- // which case it's probably an IM to everyone.
+- U8 new_dialog = dialog;
++ // default to IM_SESSION_SEND unless it's nothing special - in
++ // which case it's probably an IM to everyone.
++ U8 new_dialog = dialog;
+
+- if ( dialog != IM_NOTHING_SPECIAL )
+- {
+- new_dialog = IM_SESSION_SEND;
+- }
+- pack_instant_message(
+- gMessageSystem,
+- gAgent.getID(),
+- FALSE,
+- gAgent.getSessionID(),
+- other_participant_id,
+- name.c_str(),
+- utf8_text.c_str(),
+- offline,
+- (EInstantMessage)new_dialog,
+- im_session_id);
+- gAgent.sendReliableMessage();
++ if ( dialog != IM_NOTHING_SPECIAL )
++ {
++ new_dialog = IM_SESSION_SEND;
+ }
+
++ pack_instant_message(
++ gMessageSystem,
++ gAgent.getID(),
++ FALSE,
++ gAgent.getSessionID(),
++ other_participant_id,
++ name,
++ utf8_text,
++ offline,
++ (EInstantMessage)new_dialog,
++ im_session_id);
++ gAgent.sendReliableMessage();
++
+ // If there is a mute list and this is not a group chat...
+ if ( LLMuteList::getInstance() )
+ {
+diff --git a/linden/indra/newview/llimpanel.h b/linden/indra/newview/llimpanel.h
+index 0f9c0f3..afec6db 100644
+--- a/linden/indra/newview/llimpanel.h
++++ b/linden/indra/newview/llimpanel.h
+@@ -161,7 +161,7 @@ public:
+ /*virtual*/ void activate();
+ /*virtual*/ void getChannelInfo();
+
+- void setSessionHandle(const std::string& handle, const std::string &inURI);
++ void setSessionHandle(const std::string& handle);
+
+ protected:
+ virtual void setState(EState state);
+@@ -295,6 +295,8 @@ private:
+
+ void sendTypingState(BOOL typing);
+
++ static LLFloaterIMPanel* sInstance;
++
+ private:
+ LLLineEditor* mInputEditor;
+ LLViewerTextEditor* mHistoryEditor;
+diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp
+index 1072b21..80c6d1c 100644
+--- a/linden/indra/newview/llimview.cpp
++++ b/linden/indra/newview/llimview.cpp
+@@ -267,8 +267,7 @@ public:
+ EInstantMessage type,
+ EInvitationType inv_type,
+ const std::string& session_handle,
+- const std::string& notify_box,
+- const std::string& session_uri) :
++ const std::string& notify_box) :
+ mSessionID(session_id),
+ mSessionName(session_name),
+ mCallerID(caller_id),
+@@ -276,8 +275,7 @@ public:
+ mType(type),
+ mInvType(inv_type),
+ mSessionHandle(session_handle),
+- mNotifyBox(notify_box),
+- mSessionURI(session_uri)
++ mNotifyBox(notify_box)
+ {};
+
+ LLUUID mSessionID;
+@@ -288,7 +286,6 @@ public:
+ EInvitationType mInvType;
+ std::string mSessionHandle;
+ std::string mNotifyBox;
+- std::string mSessionURI;
+ };
+
+
+@@ -579,8 +576,7 @@ BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
+
+ LLUUID LLIMMgr::addP2PSession(const std::string& name,
+ const LLUUID& other_participant_id,
+- const std::string& voice_session_handle,
+- const std::string& caller_uri)
++ const std::string& voice_session_handle)
+ {
+ LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
+
+@@ -588,7 +584,7 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
+ if(floater)
+ {
+ LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel();
+- voice_channelp->setSessionHandle(voice_session_handle, caller_uri);
++ voice_channelp->setSessionHandle(voice_session_handle);
+ }
+
+ return session_id;
+@@ -711,8 +707,7 @@ void LLIMMgr::inviteToSession(
+ const std::string& caller_name,
+ EInstantMessage type,
+ EInvitationType inv_type,
+- const std::string& session_handle,
+- const std::string& session_uri)
++ const std::string& session_handle)
+ {
+ //ignore invites from muted residents
+ if (LLMuteList::getInstance()->isMuted(caller_id))
+@@ -754,8 +749,7 @@ void LLIMMgr::inviteToSession(
+ type,
+ inv_type,
+ session_handle,
+- notify_box_type,
+- session_uri);
++ notify_box_type);
+
+ LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
+ if (channelp && channelp->callStarted())
+@@ -930,8 +924,7 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
+ invitep->mSessionID = gIMMgr->addP2PSession(
+ invitep->mSessionName,
+ invitep->mCallerID,
+- invitep->mSessionHandle,
+- invitep->mSessionURI );
++ invitep->mSessionHandle);
+
+ LLFloaterIMPanel* im_floater =
+ gIMMgr->findFloaterBySession(
+diff --git a/linden/indra/newview/llimview.h b/linden/indra/newview/llimview.h
+index cccd6b4..cde95b5 100644
+--- a/linden/indra/newview/llimview.h
++++ b/linden/indra/newview/llimview.h
+@@ -97,8 +97,7 @@ public:
+ // Creates a P2P session with the requisite handle for responding to voice calls
+ LLUUID addP2PSession(const std::string& name,
+ const LLUUID& other_participant_id,
+- const std::string& voice_session_handle,
+- const std::string& caller_uri = LLStringUtil::null);
++ const std::string& voice_session_handle);
+
+ // This removes the panel referenced by the uuid, and then
+ // restores internal consistency. The internal pointer is not
+@@ -112,8 +111,7 @@ public:
+ const std::string& caller_name,
+ EInstantMessage type,
+ EInvitationType inv_type,
+- const std::string& session_handle = LLStringUtil::null,
+- const std::string& session_uri = LLStringUtil::null);
++ const std::string& session_handle = LLStringUtil::null);
+
+ //Updates a given session's session IDs. Does not open,
+ //create or do anything new. If the old session doesn't
+diff --git a/linden/indra/newview/llvoiceclient.cpp b/linden/indra/newview/llvoiceclient.cpp
+index 76ef87d..881beb7 100644
+--- a/linden/indra/newview/llvoiceclient.cpp
++++ b/linden/indra/newview/llvoiceclient.cpp
+@@ -1,3 +1,4 @@
++
+ /**
+ * @file llvoiceclient.cpp
+ * @brief Implementation of LLVoiceClient class which is the interface to the voice client process.
+@@ -62,20 +63,15 @@
+ #include "llviewerwindow.h"
+ #include "llviewercamera.h"
+
+-#include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel
+-#include "llfloaterchat.h" // for LLFloaterChat::addChat()
+-
+ // 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
+-
++// If we are connecting to agni AND the user's last name is "Linden", join this channel instead of looking up the sim name.
++// If we are connecting to agni and the user's last name is NOT "Linden", disable voice.
++#define AGNI_LINDENS_ONLY_CHANNEL "SL"
+ static bool sConnectingToAgni = false;
+ F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
+
+@@ -95,44 +91,6 @@ const F32 UPDATE_THROTTLE_SECONDS = 0.1f;
+ const F32 LOGIN_RETRY_SECONDS = 10.0f;
+ const int MAX_LOGIN_RETRIES = 12;
+
+-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.
+- // Map it as follows: 0.0 -> 40, 1.0 -> 44, 2.0 -> 75
+-
+- volume -= 1.0f; // offset volume to the range [-1.0 ... 1.0], with 0 at the default.
+- int scaled_volume = 44; // offset scaled_volume by its default level
+- if(volume < 0.0f)
+- scaled_volume += ((int)(volume * 4.0f)); // (44 - 40)
+- else
+- scaled_volume += ((int)(volume * 31.0f)); // (75 - 44)
+-
+- return scaled_volume;
+-}
+-
+-static int scale_speaker_volume(float volume)
+-{
+- // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
+- // Map it as follows: 0.0 -> 0, 0.5 -> 62, 1.0 -> 75
+-
+- volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
+- int scaled_volume = 62; // offset scaled_volume by its default level
+- if(volume < 0.0f)
+- scaled_volume += ((int)(volume * 124.0f)); // (62 - 0) * 2
+- else
+- scaled_volume += ((int)(volume * 26.0f)); // (75 - 62) * 2
+-
+- return scaled_volume;
+-}
+-
+ class LLViewerVoiceAccountProvisionResponder :
+ public LLHTTPClient::Responder
+ {
+@@ -146,13 +104,12 @@ public:
+ {
+ if ( mRetries > 0 )
+ {
+- LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
+ if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision(
+ mRetries - 1);
+ }
+ else
+ {
+- LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
++ //TODO: throw an error message?
+ if ( gVoiceClient ) gVoiceClient->giveUp();
+ }
+ }
+@@ -161,23 +118,9 @@ public:
+ {
+ if ( gVoiceClient )
+ {
+- std::string voice_sip_uri_hostname;
+- std::string voice_account_server_uri;
+-
+- LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+-
+- if(content.has("voice_sip_uri_hostname"))
+- voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
+-
+- // this key is actually misnamed -- it will be an entire URI, not just a hostname.
+- if(content.has("voice_account_server_name"))
+- voice_account_server_uri = content["voice_account_server_name"].asString();
+-
+ gVoiceClient->login(
+ content["username"].asString(),
+- content["password"].asString(),
+- voice_sip_uri_hostname,
+- voice_account_server_uri);
++ content["password"].asString());
+ }
+ }
+
+@@ -224,27 +167,21 @@ protected:
+ int ignoreDepth;
+
+ // Members for processing responses. The values are transient and only valid within a call to processResponse().
+- bool squelchDebugOutput;
+ int returnCode;
+ int statusCode;
+ std::string statusString;
+- std::string requestId;
++ std::string uuidString;
+ std::string actionString;
+ std::string connectorHandle;
+- std::string versionID;
+ std::string accountHandle;
+ std::string sessionHandle;
+- std::string sessionGroupHandle;
+- std::string alias;
+- std::string applicationString;
++ std::string eventSessionHandle;
+
+ // Members for processing events. The values are transient and only valid within a call to processResponse().
+ std::string eventTypeString;
+ int state;
+ std::string uriString;
+ bool isChannel;
+- bool incoming;
+- bool enabled;
+ std::string nameString;
+ std::string audioMediaString;
+ std::string displayNameString;
+@@ -254,21 +191,6 @@ protected:
+ bool isSpeaking;
+ int volume;
+ F32 energy;
+- std::string messageHeader;
+- std::string messageBody;
+- std::string notificationType;
+- bool hasText;
+- bool hasAudio;
+- bool hasVideo;
+- bool terminated;
+- std::string blockMask;
+- std::string presenceOnly;
+- std::string autoAcceptMask;
+- std::string autoAddAsBuddy;
+- int numberOfAliases;
+- std::string subscriptionHandle;
+- std::string subscriptionType;
+-
+
+ // Members for processing text between tags
+ std::string textBuffer;
+@@ -301,6 +223,8 @@ void LLVivoxProtocolParser::reset()
+ responseDepth = 0;
+ ignoringTags = false;
+ accumulateText = false;
++ textBuffer.clear();
++
+ energy = 0.f;
+ ignoreDepth = 0;
+ isChannel = false;
+@@ -309,15 +233,10 @@ void LLVivoxProtocolParser::reset()
+ isModeratorMuted = false;
+ isSpeaking = false;
+ participantType = 0;
+- squelchDebugOutput = false;
+- returnCode = -1;
++ returnCode = 0;
+ state = 0;
+ statusCode = 0;
+ volume = 0;
+- textBuffer.clear();
+- alias.clear();
+- numberOfAliases = 0;
+- applicationString.clear();
+ }
+
+ //virtual
+@@ -344,11 +263,33 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
+ mInput.append(buf, istr.gcount());
+ }
+
++ // MBW -- XXX -- This should no longer be necessary. Or even possible.
++ // We've read all the data out of the buffer. Make sure it doesn't accumulate.
++// buffer->clear();
++
+ // Look for input delimiter(s) in the input buffer. If one is found, send the message to the xml parser.
+ int start = 0;
+ int delim;
+ while((delim = mInput.find("\n\n\n", start)) != std::string::npos)
+ {
++ // Turn this on to log incoming XML
++ if(0)
++ {
++ int foo = mInput.find("Set3DPosition", start);
++ int bar = mInput.find("ParticipantPropertiesEvent", start);
++ if(foo != std::string::npos && (foo < delim))
++ {
++ // This is a Set3DPosition response. Don't print it, since these are way too spammy.
++ }
++ else if(bar != std::string::npos && (bar < delim))
++ {
++ // This is a ParticipantPropertiesEvent response. Don't print it, since these are way too spammy.
++ }
++ else
++ {
++ LL_INFOS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
++ }
++ }
+
+ // Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser)
+ reset();
+@@ -359,21 +300,15 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
+ XML_SetUserData(parser, this);
+ XML_Parse(parser, mInput.data() + start, delim - start, false);
+
+- // If this message isn't set to be squelched, output the raw XML received.
+- if(!squelchDebugOutput)
+- {
+- LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
+- }
+-
+ start = delim + 3;
+ }
+
+ if(start != 0)
+ mInput = mInput.substr(start);
+
+- LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL;
+-
+- if(!gVoiceClient->mConnected)
++ LL_DEBUGS("Voice") << "at end, mInput is: " << mInput << LL_ENDL;
++
++ if((!gVoiceClient)||((gVoiceClient)&&(!gVoiceClient->mConnected)))
+ {
+ // If voice has been disabled, we just want to close the socket. This does so.
+ LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL;
+@@ -426,9 +361,9 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
+
+ if (responseDepth == 0)
+ {
+- isEvent = !stricmp("Event", tag);
++ isEvent = strcmp("Event", tag) == 0;
+
+- if (!stricmp("Response", tag) || isEvent)
++ if (strcmp("Response", tag) == 0 || isEvent)
+ {
+ // Grab the attributes
+ while (*attr)
+@@ -436,62 +371,49 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
+ const char *key = *attr++;
+ const char *value = *attr++;
+
+- if (!stricmp("requestId", key))
++ if (strcmp("requestId", key) == 0)
+ {
+- requestId = value;
++ uuidString = value;
+ }
+- else if (!stricmp("action", key))
++ else if (strcmp("action", key) == 0)
+ {
+ actionString = value;
+ }
+- else if (!stricmp("type", key))
++ else if (strcmp("type", key) == 0)
+ {
+ eventTypeString = value;
+ }
+ }
+ }
+- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
++ LL_DEBUGS("Voice") << tag << " (" << responseDepth << ")" << LL_ENDL;
+ }
+ else
+ {
+ if (ignoringTags)
+ {
+- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
++ LL_DEBUGS("Voice") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
+ }
+ else
+ {
+- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
++ LL_DEBUGS("Voice") << tag << " (" << responseDepth << ")" << LL_ENDL;
+
+ // Ignore the InputXml stuff so we don't get confused
+- if (!stricmp("InputXml", tag))
++ if (strcmp("InputXml", tag) == 0)
+ {
+ ignoringTags = true;
+ ignoreDepth = responseDepth;
+ accumulateText = false;
+
+- LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
++ LL_DEBUGS("Voice") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
+ }
+- else if (!stricmp("CaptureDevices", tag))
++ else if (strcmp("CaptureDevices", tag) == 0)
+ {
+ gVoiceClient->clearCaptureDevices();
+ }
+- else if (!stricmp("RenderDevices", tag))
++ else if (strcmp("RenderDevices", tag) == 0)
+ {
+ gVoiceClient->clearRenderDevices();
+ }
+- else if (!stricmp("Buddies", tag))
+- {
+- gVoiceClient->deleteAllBuddies();
+- }
+- else if (!stricmp("BlockRules", tag))
+- {
+- gVoiceClient->deleteAllBlockRules();
+- }
+- else if (!stricmp("AutoAcceptRules", tag))
+- {
+- gVoiceClient->deleteAllAutoAcceptRules();
+- }
+-
+ }
+ }
+ responseDepth++;
+@@ -510,138 +432,90 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
+ {
+ if (ignoreDepth == responseDepth)
+ {
+- LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL;
++ LL_DEBUGS("Voice") << "end of ignore" << LL_ENDL;
+ ignoringTags = false;
+ }
+ else
+ {
+- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
++ LL_DEBUGS("Voice") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
+ }
+ }
+
+ if (!ignoringTags)
+ {
+- LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
++ LL_DEBUGS("Voice") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
+
+ // Closing a tag. Finalize the text we've accumulated and reset
+- if (!stricmp("ReturnCode", tag))
++ if (strcmp("ReturnCode", tag) == 0)
+ returnCode = strtol(string.c_str(), NULL, 10);
+- else if (!stricmp("SessionHandle", tag))
+- sessionHandle = string;
+- else if (!stricmp("SessionGroupHandle", tag))
+- sessionGroupHandle = string;
+- else if (!stricmp("StatusCode", tag))
++ else if (strcmp("StatusCode", tag) == 0)
+ statusCode = strtol(string.c_str(), NULL, 10);
+- else if (!stricmp("StatusString", tag))
+- statusString = string;
+- else if (!stricmp("ParticipantURI", tag))
+- uriString = string;
+- else if (!stricmp("Volume", tag))
+- volume = strtol(string.c_str(), NULL, 10);
+- else if (!stricmp("Energy", tag))
+- energy = (F32)strtod(string.c_str(), NULL);
+- else if (!stricmp("IsModeratorMuted", tag))
+- isModeratorMuted = !stricmp(string.c_str(), "true");
+- else if (!stricmp("IsSpeaking", tag))
+- isSpeaking = !stricmp(string.c_str(), "true");
+- else if (!stricmp("Alias", tag))
+- alias = string;
+- else if (!stricmp("NumberOfAliases", tag))
+- numberOfAliases = strtol(string.c_str(), NULL, 10);
+- else if (!stricmp("Application", tag))
+- applicationString = string;
+- else if (!stricmp("ConnectorHandle", tag))
++ else if (strcmp("ConnectorHandle", tag) == 0)
+ connectorHandle = string;
+- else if (!stricmp("VersionID", tag))
+- versionID = string;
+- else if (!stricmp("AccountHandle", tag))
++ else if (strcmp("AccountHandle", tag) == 0)
+ accountHandle = string;
+- else if (!stricmp("State", tag))
++ else if (strcmp("SessionHandle", tag) == 0)
++ {
++ if (isEvent)
++ eventSessionHandle = string;
++ else
++ sessionHandle = string;
++ }
++ else if (strcmp("StatusString", tag) == 0)
++ statusString = string;
++ else if (strcmp("State", tag) == 0)
+ state = strtol(string.c_str(), NULL, 10);
+- else if (!stricmp("URI", tag))
++ else if (strcmp("URI", tag) == 0)
+ uriString = string;
+- else if (!stricmp("IsChannel", tag))
+- isChannel = !stricmp(string.c_str(), "true");
+- else if (!stricmp("Incoming", tag))
+- incoming = !stricmp(string.c_str(), "true");
+- else if (!stricmp("Enabled", tag))
+- enabled = !stricmp(string.c_str(), "true");
+- else if (!stricmp("Name", tag))
++ else if (strcmp("IsChannel", tag) == 0)
++ isChannel = string == "true" ? true : false;
++ else if (strcmp("Name", tag) == 0)
+ nameString = string;
+- else if (!stricmp("AudioMedia", tag))
++ else if (strcmp("AudioMedia", tag) == 0)
+ audioMediaString = string;
+- else if (!stricmp("ChannelName", tag))
++ else if (strcmp("ChannelName", tag) == 0)
+ nameString = string;
+- else if (!stricmp("DisplayName", tag))
++ else if (strcmp("ParticipantURI", tag) == 0)
++ uriString = string;
++ else if (strcmp("DisplayName", tag) == 0)
+ displayNameString = string;
+- else if (!stricmp("AccountName", tag))
++ else if (strcmp("AccountName", tag) == 0)
+ nameString = string;
+- else if (!stricmp("ParticipantType", tag))
++ else if (strcmp("ParticipantTyppe", tag) == 0)
+ participantType = strtol(string.c_str(), NULL, 10);
+- else if (!stricmp("IsLocallyMuted", tag))
+- isLocallyMuted = !stricmp(string.c_str(), "true");
+- else if (!stricmp("MicEnergy", tag))
++ else if (strcmp("IsLocallyMuted", tag) == 0)
++ isLocallyMuted = string == "true" ? true : false;
++ else if (strcmp("IsModeratorMuted", tag) == 0)
++ isModeratorMuted = string == "true" ? true : false;
++ else if (strcmp("IsSpeaking", tag) == 0)
++ isSpeaking = string == "true" ? true : false;
++ else if (strcmp("Volume", tag) == 0)
++ volume = strtol(string.c_str(), NULL, 10);
++ else if (strcmp("Energy", tag) == 0)
+ energy = (F32)strtod(string.c_str(), NULL);
+- else if (!stricmp("ChannelName", tag))
++ else if (strcmp("MicEnergy", tag) == 0)
++ energy = (F32)strtod(string.c_str(), NULL);
++ else if (strcmp("ChannelName", tag) == 0)
+ nameString = string;
+- else if (!stricmp("ChannelURI", tag))
+- uriString = string;
+- else if (!stricmp("BuddyURI", tag))
++ else if (strcmp("ChannelURI", tag) == 0)
+ uriString = string;
+- else if (!stricmp("Presence", tag))
+- statusString = string;
+- else if (!stricmp("Device", tag))
++ else if (strcmp("ChannelListResult", tag) == 0)
++ {
++ gVoiceClient->addChannelMapEntry(nameString, uriString);
++ }
++ else if (strcmp("Device", tag) == 0)
+ {
+ // This closing tag shouldn't clear the accumulated text.
+ clearbuffer = false;
+ }
+- else if (!stricmp("CaptureDevice", tag))
++ else if (strcmp("CaptureDevice", tag) == 0)
+ {
+ gVoiceClient->addCaptureDevice(textBuffer);
+ }
+- else if (!stricmp("RenderDevice", tag))
++ else if (strcmp("RenderDevice", tag) == 0)
+ {
+ gVoiceClient->addRenderDevice(textBuffer);
+ }
+- else if (!stricmp("Buddy", tag))
+- {
+- gVoiceClient->processBuddyListEntry(uriString, displayNameString);
+- }
+- else if (!stricmp("BlockRule", tag))
+- {
+- gVoiceClient->addBlockRule(blockMask, presenceOnly);
+- }
+- else if (!stricmp("BlockMask", tag))
+- blockMask = string;
+- else if (!stricmp("PresenceOnly", tag))
+- presenceOnly = string;
+- else if (!stricmp("AutoAcceptRule", tag))
+- {
+- gVoiceClient->addAutoAcceptRule(autoAcceptMask, autoAddAsBuddy);
+- }
+- else if (!stricmp("AutoAcceptMask", tag))
+- autoAcceptMask = string;
+- else if (!stricmp("AutoAddAsBuddy", tag))
+- autoAddAsBuddy = string;
+- else if (!stricmp("MessageHeader", tag))
+- messageHeader = string;
+- else if (!stricmp("MessageBody", tag))
+- messageBody = string;
+- else if (!stricmp("NotificationType", tag))
+- notificationType = string;
+- else if (!stricmp("HasText", tag))
+- hasText = !stricmp(string.c_str(), "true");
+- else if (!stricmp("HasAudio", tag))
+- hasAudio = !stricmp(string.c_str(), "true");
+- else if (!stricmp("HasVideo", tag))
+- hasVideo = !stricmp(string.c_str(), "true");
+- else if (!stricmp("Terminated", tag))
+- terminated = !stricmp(string.c_str(), "true");
+- else if (!stricmp("SubscriptionHandle", tag))
+- subscriptionHandle = string;
+- else if (!stricmp("SubscriptionType", tag))
+- subscriptionType = string;
+-
+
+ if(clearbuffer)
+ {
+@@ -676,296 +550,147 @@ void LLVivoxProtocolParser::CharData(const char *buffer, int length)
+
+ void LLVivoxProtocolParser::processResponse(std::string tag)
+ {
+- LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL;
++ LL_DEBUGS("Voice") << tag << LL_ENDL;
++
++ if (!gVoiceClient)
++ return;
+
+- // SLIM SDK: the SDK now returns a statusCode of "200" (OK) for success. This is a change vs. previous SDKs.
+- // According to Mike S., "The actual API convention is that responses with return codes of 0 are successful, regardless of the status code returned",
+- // so I believe this will give correct behavior.
+-
+- if(returnCode == 0)
+- statusCode = 0;
+-
+ if (isEvent)
+ {
+- const char *eventTypeCstr = eventTypeString.c_str();
+- if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
++ if (eventTypeString == "LoginStateChangeEvent")
+ {
+- gVoiceClient->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state);
++ gVoiceClient->loginStateChangeEvent(accountHandle, statusCode, statusString, state);
+ }
+- else if (!stricmp(eventTypeCstr, "SessionAddedEvent"))
+- {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
+- sip:confctl-1408789@bhr.vivox.com
+- true
+- false
+-
+-
+- */
+- gVoiceClient->sessionAddedEvent(uriString, alias, sessionHandle, sessionGroupHandle, isChannel, incoming, nameString, applicationString);
+- }
+- else if (!stricmp(eventTypeCstr, "SessionRemovedEvent"))
+- {
+- gVoiceClient->sessionRemovedEvent(sessionHandle, sessionGroupHandle);
+- }
+- else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent"))
+- {
+- gVoiceClient->sessionGroupAddedEvent(sessionGroupHandle);
+- }
+- else if (!stricmp(eventTypeCstr, "MediaStreamUpdatedEvent"))
+- {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
+- 200
+- OK
+- 2
+- false
+-
+- */
+- gVoiceClient->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming);
+- }
+- else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent"))
++ else if (eventTypeString == "SessionNewEvent")
+ {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg1
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==1
+- true
+- 1
+- true
+-
+- */
+- gVoiceClient->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming);
++ gVoiceClient->sessionNewEvent(accountHandle, eventSessionHandle, state, nameString, uriString);
+ }
+- else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent"))
++ else if (eventTypeString == "SessionStateChangeEvent")
+ {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==4
+- sip:xI5auBZ60SJWIk606-1JGRQ==@bhr.vivox.com
+- xI5auBZ60SJWIk606-1JGRQ==
+-
+- 0
+-
+- */
+- gVoiceClient->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
++ gVoiceClient->sessionStateChangeEvent(uriString, statusCode, statusString, eventSessionHandle, state, isChannel, nameString);
+ }
+- else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
++ else if (eventTypeString == "ParticipantStateChangeEvent")
+ {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==4
+- sip:xtx7YNV-3SGiG7rA1fo5Ndw==@bhr.vivox.com
+- xtx7YNV-3SGiG7rA1fo5Ndw==
+-
+- */
+- gVoiceClient->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
+- }
+- else if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
+- {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
+- sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com
+- false
+- true
+- 44
+- 0.0879437
+-
+- */
++ gVoiceClient->participantStateChangeEvent(uriString, statusCode, statusString, state, nameString, displayNameString, participantType);
+
+- // These happen so often that logging them is pretty useless.
+- squelchDebugOutput = true;
+-
+- gVoiceClient->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
+- }
+- else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))
+- {
+- gVoiceClient->auxAudioPropertiesEvent(energy);
+- }
+- else if (!stricmp(eventTypeCstr, "BuddyPresenceEvent"))
+- {
+- gVoiceClient->buddyPresenceEvent(uriString, alias, statusString, applicationString);
+- }
+- else if (!stricmp(eventTypeCstr, "BuddyAndGroupListChangedEvent"))
+- {
+- // The buddy list was updated during parsing.
+- // Need to recheck against the friends list.
+- gVoiceClient->buddyListChanged();
+- }
+- else if (!stricmp(eventTypeCstr, "BuddyChangedEvent"))
+- {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==
+- sip:x9fFHFZjOTN6OESF1DUPrZQ==@bhr.vivox.com
+- Monroe Tester
+-
+- 0
+- Set
+-
+- */
+- // TODO: Question: Do we need to process this at all?
+- }
+- else if (!stricmp(eventTypeCstr, "MessageEvent"))
+- {
+- gVoiceClient->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString);
+ }
+- else if (!stricmp(eventTypeCstr, "SessionNotificationEvent"))
++ else if (eventTypeString == "ParticipantPropertiesEvent")
+ {
+- gVoiceClient->sessionNotificationEvent(sessionHandle, uriString, notificationType);
++ gVoiceClient->participantPropertiesEvent(uriString, statusCode, statusString, isLocallyMuted, isModeratorMuted, isSpeaking, volume, energy);
+ }
+- else if (!stricmp(eventTypeCstr, "SubscriptionEvent"))
++ else if (eventTypeString == "AuxAudioPropertiesEvent")
+ {
+- gVoiceClient->subscriptionEvent(uriString, subscriptionHandle, alias, displayNameString, applicationString, subscriptionType);
+- }
+- else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))
+- {
+- /*
+-
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
+- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
+- sip:confctl-9@bhd.vivox.com
+- 0
+- 50
+- 1
+- 0
+- 000
+- 0
+-
+- */
+- // We don't need to process this, but we also shouldn't warn on it, since that confuses people.
+- }
+- else
+- {
+- LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
++ gVoiceClient->auxAudioPropertiesEvent(energy);
+ }
+ }
+ else
+ {
+- const char *actionCstr = actionString.c_str();
+- if (!stricmp(actionCstr, "Connector.Create.1"))
++ if (actionString == "Connector.Create.1")
+ {
+- gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID);
++ gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle);
+ }
+- else if (!stricmp(actionCstr, "Account.Login.1"))
++ else if (actionString == "Account.Login.1")
+ {
+- gVoiceClient->loginResponse(statusCode, statusString, accountHandle, numberOfAliases);
++ gVoiceClient->loginResponse(statusCode, statusString, accountHandle);
+ }
+- else if (!stricmp(actionCstr, "Session.Create.1"))
++ else if (actionString == "Session.Create.1")
+ {
+- gVoiceClient->sessionCreateResponse(requestId, statusCode, statusString, sessionHandle);
++ gVoiceClient->sessionCreateResponse(statusCode, statusString, sessionHandle);
+ }
+- else if (!stricmp(actionCstr, "SessionGroup.AddSession.1"))
++ else if (actionString == "Session.Connect.1")
+ {
+- gVoiceClient->sessionGroupAddSessionResponse(requestId, statusCode, statusString, sessionHandle);
++ gVoiceClient->sessionConnectResponse(statusCode, statusString);
+ }
+- else if (!stricmp(actionCstr, "Session.Connect.1"))
++ else if (actionString == "Session.Terminate.1")
+ {
+- gVoiceClient->sessionConnectResponse(requestId, statusCode, statusString);
++ gVoiceClient->sessionTerminateResponse(statusCode, statusString);
+ }
+- else if (!stricmp(actionCstr, "Account.Logout.1"))
++ else if (actionString == "Account.Logout.1")
+ {
+ gVoiceClient->logoutResponse(statusCode, statusString);
+ }
+- else if (!stricmp(actionCstr, "Connector.InitiateShutdown.1"))
++ else if (actionString == "Connector.InitiateShutdown.1")
+ {
+ gVoiceClient->connectorShutdownResponse(statusCode, statusString);
+ }
+- else if (!stricmp(actionCstr, "Account.ListBlockRules.1"))
+- {
+- gVoiceClient->accountListBlockRulesResponse(statusCode, statusString);
+- }
+- else if (!stricmp(actionCstr, "Account.ListAutoAcceptRules.1"))
+- {
+- gVoiceClient->accountListAutoAcceptRulesResponse(statusCode, statusString);
+- }
+- else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
++ else if (actionString == "Account.ChannelGetList.1")
+ {
+- // We don't need to process these, but they're so spammy we don't want to log them.
+- squelchDebugOutput = true;
++ gVoiceClient->channelGetListResponse(statusCode, statusString);
+ }
+ /*
+- else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
++ else if (actionString == "Connector.AccountCreate.1")
+ {
+- gVoiceClient->channelGetListResponse(statusCode, statusString);
++
+ }
+- else if (!stricmp(actionCstr, "Connector.AccountCreate.1"))
++ else if (actionString == "Connector.MuteLocalMic.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Connector.MuteLocalMic.1"))
++ else if (actionString == "Connector.MuteLocalSpeaker.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Connector.MuteLocalSpeaker.1"))
++ else if (actionString == "Connector.SetLocalMicVolume.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Connector.SetLocalMicVolume.1"))
++ else if (actionString == "Connector.SetLocalSpeakerVolume.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Connector.SetLocalSpeakerVolume.1"))
++ else if (actionString == "Session.ListenerSetPosition.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Session.ListenerSetPosition.1"))
++ else if (actionString == "Session.SpeakerSetPosition.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Session.SpeakerSetPosition.1"))
++ else if (actionString == "Session.Set3DPosition.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Session.AudioSourceSetPosition.1"))
++ else if (actionString == "Session.AudioSourceSetPosition.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Session.GetChannelParticipants.1"))
++ else if (actionString == "Session.GetChannelParticipants.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelCreate.1"))
++ else if (actionString == "Account.ChannelCreate.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelUpdate.1"))
++ else if (actionString == "Account.ChannelUpdate.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelDelete.1"))
++ else if (actionString == "Account.ChannelDelete.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelCreateAndInvite.1"))
++ else if (actionString == "Account.ChannelCreateAndInvite.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelFolderCreate.1"))
++ else if (actionString == "Account.ChannelFolderCreate.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelFolderUpdate.1"))
++ else if (actionString == "Account.ChannelFolderUpdate.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelFolderDelete.1"))
++ else if (actionString == "Account.ChannelFolderDelete.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelAddModerator.1"))
++ else if (actionString == "Account.ChannelAddModerator.1")
+ {
+
+ }
+- else if (!stricmp(actionCstr, "Account.ChannelDeleteModerator.1"))
++ else if (actionString == "Account.ChannelDeleteModerator.1")
+ {
+
+ }
+@@ -979,18 +704,9 @@ class LLVoiceClientMuteListObserver : public LLMuteListObserver
+ {
+ /* virtual */ void onChange() { gVoiceClient->muteListChanged();}
+ };
+-
+-class LLVoiceClientFriendsObserver : public LLFriendObserver
+-{
+-public:
+- /* virtual */ void changed(U32 mask) { gVoiceClient->updateFriends(mask);}
+-};
+-
+ static LLVoiceClientMuteListObserver mutelist_listener;
+ static bool sMuteListListener_listening = false;
+
+-static LLVoiceClientFriendsObserver *friendslist_listener = NULL;
+-
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+ class LLVoiceClientCapResponder : public LLHTTPClient::Responder
+@@ -1014,8 +730,11 @@ void LLVoiceClientCapResponder::error(U32 status, const std::string& reason)
+ void LLVoiceClientCapResponder::result(const LLSD& content)
+ {
+ LLSD::map_const_iterator iter;
+-
+- LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
++ for(iter = content.beginMap(); iter != content.endMap(); ++iter)
++ {
++ LL_DEBUGS("Voice") << "LLVoiceClientCapResponder::result got "
++ << iter->first << LL_ENDL;
++ }
+
+ if ( content.has("voice_credentials") )
+ {
+@@ -1101,26 +820,26 @@ LLVoiceClient::LLVoiceClient()
+ mUserPTTState = false;
+ mMuteMic = false;
+ mSessionTerminateRequested = false;
+- mRelogRequested = false;
+ mCommandCookie = 0;
++ mNonSpatialChannel = false;
++ mNextSessionSpatial = true;
++ mNextSessionNoReconnect = false;
++ mSessionP2P = false;
+ mCurrentParcelLocalID = 0;
+ mLoginRetryCount = 0;
++ mVivoxErrorStatusCode = 0;
+
++ mNextSessionResetOnClose = false;
++ mSessionResetOnClose = false;
+ mSpeakerVolume = 0;
+ mMicVolume = 0;
+
+- mAudioSession = NULL;
+- mAudioSessionChanged = false;
+-
+ // Initial dirty state
+ mSpatialCoordsDirty = false;
+ mPTTDirty = true;
+- mFriendsListDirty = true;
++ mVolumeDirty = true;
+ mSpeakerVolumeDirty = true;
+ mMicVolumeDirty = true;
+- mBuddyListMapPopulated = false;
+- mBlockRulesListReceived = false;
+- mAutoAcceptRulesListReceived = false;
+ mCaptureDeviceDirty = false;
+ mRenderDeviceDirty = false;
+
+@@ -1141,12 +860,14 @@ LLVoiceClient::LLVoiceClient()
+ // gMuteListp isn't set up at this point, so we defer this until later.
+ // gMuteListp->addObserver(&mutelist_listener);
+
++ mParticipantMapChanged = false;
++
+ // stash the pump for later use
+ // This now happens when init() is called instead.
+ mPump = NULL;
+
+ #if LL_DARWIN || LL_LINUX
+- // HACK: THIS DOES NOT BELONG HERE
++ // MBW -- XXX -- THIS DOES NOT BELONG HERE
+ // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
+ // This should cause us to ignore SIGPIPE and handle the error through proper channels.
+ // This should really be set up elsewhere. Where should it go?
+@@ -1182,10 +903,8 @@ void LLVoiceClient::terminate()
+ {
+ if(gVoiceClient)
+ {
+-// gVoiceClient->leaveAudioSession();
++ gVoiceClient->sessionTerminateSendMessage();
+ gVoiceClient->logout();
+- // As of SDK version 4885, this should no longer be necessary. It will linger after the socket close if it needs to.
+- // ms_sleep(2000);
+ gVoiceClient->connectorShutdown();
+ gVoiceClient->closeSocket(); // Need to do this now -- bad things happen if the destructor does it later.
+
+@@ -1210,13 +929,13 @@ void LLVoiceClient::updateSettings()
+ setPTTKey(keyString);
+ setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
+ setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
++ std::string serverName = gSavedSettings.getString("VivoxDebugServerName");
++ setVivoxDebugServerName(serverName);
+
+ std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
+ setCaptureDevice(inputDevice);
+ std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
+ setRenderDevice(outputDevice);
+- F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
+- setMicGain(mic_level);
+ setLipSyncEnabled(gSavedSettings.getBOOL("LipSyncEnabled"));
+ }
+
+@@ -1232,10 +951,9 @@ bool LLVoiceClient::writeString(const std::string &str)
+ apr_size_t size = (apr_size_t)str.size();
+ apr_size_t written = size;
+
+- //MARK: Turn this on to log outgoing XML
+-// LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
++ LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
+
+- // check return code - sockets will fail (broken, etc.)
++ // MBW -- XXX -- check return code - sockets will fail (broken, etc.)
+ err = apr_socket_send(
+ mSocket->getSocket(),
+ (const char*)str.data(),
+@@ -1246,7 +964,7 @@ bool LLVoiceClient::writeString(const std::string &str)
+ // Success.
+ result = true;
+ }
+- // TODO: handle partial writes (written is number of bytes written)
++ // MBW -- XXX -- handle partial writes (written is number of bytes written)
+ // Need to set socket to non-blocking before this will work.
+ // else if(APR_STATUS_IS_EAGAIN(err))
+ // {
+@@ -1270,7 +988,7 @@ bool LLVoiceClient::writeString(const std::string &str)
+ void LLVoiceClient::connectorCreate()
+ {
+ std::ostringstream stream;
+- std::string logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
++ std::string logpath;
+ std::string loglevel = "0";
+
+ // Transition to stateConnectorStarted when the connector handle comes back.
+@@ -1282,20 +1000,20 @@ void LLVoiceClient::connectorCreate()
+ {
+ LL_DEBUGS("Voice") << "creating connector with logging enabled" << LL_ENDL;
+ loglevel = "10";
++ logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+ }
+
+ stream
+ << ""
+ << "V2 SDK"
+- << "" << mVoiceAccountServerURI << ""
+- << "Normal"
++ << "" << mAccountServerURI << ""
+ << ""
++ << "false"
+ << "" << logpath << ""
+ << "Connector"
+ << ".log"
+ << "" << loglevel << ""
+ << ""
+- << "SecondLifeViewer.1"
+ << "\n\n\n";
+
+ writeString(stream.str());
+@@ -1333,6 +1051,20 @@ void LLVoiceClient::userAuthorized(const std::string& firstName, const std::stri
+
+ sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid();
+
++ // MBW -- XXX -- Enable this when the bhd.vivox.com server gets a real ssl cert.
++ if(sConnectingToAgni)
++ {
++ // Use the release account server
++ mAccountServerName = "bhr.vivox.com";
++ mAccountServerURI = "https://www." + mAccountServerName + "/api2/";
++ }
++ else
++ {
++ // Use the development account server
++ mAccountServerName = gSavedSettings.getString("VivoxDebugServerName");
++ mAccountServerURI = "https://www." + mAccountServerName + "/api2/";
++ }
++
+ mAccountName = nameFromID(agentID);
+ }
+
+@@ -1354,69 +1086,24 @@ void LLVoiceClient::requestVoiceAccountProvision(S32 retries)
+ }
+
+ void LLVoiceClient::login(
+- const std::string& account_name,
+- const std::string& password,
+- const std::string& voice_sip_uri_hostname,
+- const std::string& voice_account_server_uri)
++ const std::string& accountName,
++ const std::string &password)
+ {
+- mVoiceSIPURIHostName = voice_sip_uri_hostname;
+- mVoiceAccountServerURI = voice_account_server_uri;
+-
+- if(!mAccountHandle.empty())
++ if((getState() >= stateLoggingIn) && (getState() < stateLoggedOut))
+ {
+- // Already logged in.
+- LL_WARNS("Voice") << "Called while already logged in." << LL_ENDL;
+-
+- // Don't process another login.
+- return;
++ // Already logged in. This is an internal error.
++ LL_ERRS("Voice") << "Can't login again. Called from wrong state." << LL_ENDL;
+ }
+- else if ( account_name != mAccountName )
++ else if ( accountName != mAccountName )
+ {
+ //TODO: error?
+- LL_WARNS("Voice") << "Wrong account name! " << account_name
++ LL_WARNS("Voice") << "Wrong account name! " << accountName
+ << " instead of " << mAccountName << LL_ENDL;
+ }
+ else
+ {
+ mAccountPassword = password;
+ }
+-
+- std::string debugSIPURIHostName = gSavedSettings.getString("VivoxDebugSIPURIHostName");
+-
+- if( !debugSIPURIHostName.empty() )
+- {
+- mVoiceSIPURIHostName = debugSIPURIHostName;
+- }
+-
+- if( mVoiceSIPURIHostName.empty() )
+- {
+- // we have an empty account server name
+- // so we fall back to hardcoded defaults
+-
+- if(sConnectingToAgni)
+- {
+- // Use the release account server
+- mVoiceSIPURIHostName = "bhr.vivox.com";
+- }
+- else
+- {
+- // Use the development account server
+- mVoiceSIPURIHostName = "bhd.vivox.com";
+- }
+- }
+-
+- std::string debugAccountServerURI = gSavedSettings.getString("VivoxDebugVoiceAccountServerURI");
+-
+- if( !debugAccountServerURI.empty() )
+- {
+- mVoiceAccountServerURI = debugAccountServerURI;
+- }
+-
+- if( mVoiceAccountServerURI.empty() )
+- {
+- // If the account server URI isn't specified, construct it from the SIP URI hostname
+- mVoiceAccountServerURI = "https://www." + mVoiceSIPURIHostName + "/api2/";
+- }
+ }
+
+ void LLVoiceClient::idle(void* user_data)
+@@ -1434,16 +1121,11 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
+
+ switch(inState)
+ {
+- CASE(stateDisableCleanup);
+ CASE(stateDisabled);
+ CASE(stateStart);
+ CASE(stateDaemonLaunched);
+ CASE(stateConnecting);
+- CASE(stateConnected);
+ CASE(stateIdle);
+- CASE(stateMicTuningStart);
+- CASE(stateMicTuningRunning);
+- CASE(stateMicTuningStop);
+ CASE(stateConnectorStart);
+ CASE(stateConnectorStarting);
+ CASE(stateConnectorStarted);
+@@ -1452,8 +1134,12 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
+ CASE(stateNeedsLogin);
+ CASE(stateLoggingIn);
+ CASE(stateLoggedIn);
+- CASE(stateCreatingSessionGroup);
+ CASE(stateNoChannel);
++ CASE(stateMicTuningStart);
++ CASE(stateMicTuningRunning);
++ CASE(stateMicTuningStop);
++ CASE(stateSessionCreate);
++ CASE(stateSessionConnect);
+ CASE(stateJoiningSession);
+ CASE(stateSessionJoined);
+ CASE(stateRunning);
+@@ -1470,6 +1156,7 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
+ CASE(stateJoinSessionFailed);
+ CASE(stateJoinSessionFailedWaiting);
+ CASE(stateJail);
++ CASE(stateMicTuningNoLogin);
+ }
+
+ #undef CASE
+@@ -1491,7 +1178,6 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv
+ CASE(STATUS_JOINING);
+ CASE(STATUS_JOINED);
+ CASE(STATUS_LEFT_CHANNEL);
+- CASE(STATUS_VOICE_DISABLED);
+ CASE(BEGIN_ERROR_STATUS);
+ CASE(ERROR_CHANNEL_FULL);
+ CASE(ERROR_CHANNEL_LOCKED);
+@@ -1525,13 +1211,9 @@ void LLVoiceClient::stateMachine()
+ {
+ updatePosition();
+ }
+- else if(mTuningMode)
+- {
+- // Tuning mode is special -- it needs to launch SLVoice even if voice is disabled.
+- }
+ else
+ {
+- if((getState() != stateDisabled) && (getState() != stateDisableCleanup))
++ if(getState() != stateDisabled)
+ {
+ // User turned off voice support. Send the cleanup messages, close the socket, and reset.
+ if(!mConnected)
+@@ -1541,10 +1223,13 @@ void LLVoiceClient::stateMachine()
+ killGateway();
+ }
+
++ sessionTerminateSendMessage();
+ logout();
+ connectorShutdown();
+-
+- setState(stateDisableCleanup);
++ closeSocket();
++ removeAllParticipants();
++
++ setState(stateDisabled);
+ }
+ }
+
+@@ -1559,7 +1244,7 @@ void LLVoiceClient::stateMachine()
+ std::string regionName = region->getName();
+ std::string capURI = region->getCapability("ParcelVoiceInfoRequest");
+
+-// LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL;
++ LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL;
+
+ // The region name starts out empty and gets filled in later.
+ // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
+@@ -1580,30 +1265,13 @@ void LLVoiceClient::stateMachine()
+
+ switch(getState())
+ {
+- //MARK: stateDisableCleanup
+- case stateDisableCleanup:
+- // Clean up and reset everything.
+- closeSocket();
+- deleteAllSessions();
+- deleteAllBuddies();
+-
+- mConnectorHandle.clear();
+- mAccountHandle.clear();
+- mAccountPassword.clear();
+- mVoiceAccountServerURI.clear();
+-
+- setState(stateDisabled);
+- break;
+-
+- //MARK: stateDisabled
+ case stateDisabled:
+- if(mTuningMode || (mVoiceEnabled && !mAccountName.empty()))
++ if(mVoiceEnabled && (!mAccountName.empty() || mTuningMode))
+ {
+ setState(stateStart);
+ }
+ break;
+
+- //MARK: stateStart
+ case stateStart:
+ if(gSavedSettings.getBOOL("CmdLineDisableVoice"))
+ {
+@@ -1634,9 +1302,7 @@ void LLVoiceClient::stateMachine()
+ if(!LLFile::stat(exe_path, &s))
+ {
+ // vivox executable exists. Build the command line and launch the daemon.
+- // SLIM SDK: these arguments are no longer necessary.
+-// std::string args = " -p tcp -h -c";
+- std::string args;
++ std::string args = " -p tcp -h -c";
+ std::string cmd;
+ std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
+
+@@ -1721,15 +1387,14 @@ void LLVoiceClient::stateMachine()
+ }
+ else
+ {
+- LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL;
++ LL_INFOS("Voice") << exe_path << "not found." << LL_ENDL;
+ }
+ }
+ else
+ {
+- // SLIM SDK: port changed from 44124 to 44125.
+ // We can connect to a client gateway running on another host. This is useful for testing.
+ // To do this, launch the gateway on a nearby host like this:
+- // vivox-gw.exe -p tcp -i 0.0.0.0:44125
++ // vivox-gw.exe -p tcp -i 0.0.0.0:44124
+ // and put that host's IP address here.
+ mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost"), gSavedSettings.getU32("VoicePort"));
+ }
+@@ -1741,23 +1406,17 @@ void LLVoiceClient::stateMachine()
+
+ // Dirty the states we'll need to sync with the daemon when it comes up.
+ mPTTDirty = true;
+- mMicVolumeDirty = true;
+ mSpeakerVolumeDirty = true;
+- mSpeakerMuteDirty = true;
+ // These only need to be set if they're not default (i.e. empty string).
+ mCaptureDeviceDirty = !mCaptureDevice.empty();
+ mRenderDeviceDirty = !mRenderDevice.empty();
+-
+- mMainSessionGroupHandle.clear();
+ }
+ break;
+-
+- //MARK: stateDaemonLaunched
++
+ case stateDaemonLaunched:
++ LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
+ if(mUpdateTimer.hasExpired())
+ {
+- LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
+-
+ mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
+
+ if(!mSocket)
+@@ -1778,7 +1437,6 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateConnecting
+ case stateConnecting:
+ // Can't do this until we have the pump available.
+ if(mPump)
+@@ -1796,34 +1454,48 @@ void LLVoiceClient::stateMachine()
+
+ mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
+
+- setState(stateConnected);
++ setState(stateIdle);
+ }
+
+ break;
+
+- //MARK: stateConnected
+- case stateConnected:
++ case stateIdle:
+ // Initial devices query
+ getCaptureDevicesSendMessage();
+ getRenderDevicesSendMessage();
+
+ mLoginRetryCount = 0;
+-
+- setState(stateIdle);
++
++ setState(stateConnectorStart);
++
+ break;
+-
+- //MARK: stateIdle
+- case stateIdle:
+- // This is the idle state where we're connected to the daemon but haven't set up a connector yet.
+- if(mTuningMode)
++
++ case stateConnectorStart:
++ if(!mVoiceEnabled)
+ {
+- mTuningExitState = stateIdle;
++ // We were never logged in. This will shut down the connector.
++ setState(stateLoggedOut);
++ }
++ else if(!mAccountServerURI.empty())
++ {
++ connectorCreate();
++ }
++ else if(mTuningMode)
++ {
++ mTuningExitState = stateConnectorStart;
+ setState(stateMicTuningStart);
+ }
+- else if(!mVoiceEnabled)
++ break;
++
++ case stateConnectorStarting: // waiting for connector handle
++ // connectorCreateResponse() will transition from here to stateConnectorStarted.
++ break;
++
++ case stateConnectorStarted: // connector handle received
++ if(!mVoiceEnabled)
+ {
+- // We never started up the connector. This will shut down the daemon.
+- setState(stateConnectorStopped);
++ // We were never logged in. This will shut down the connector.
++ setState(stateLoggedOut);
+ }
+ else if(!mAccountName.empty())
+ {
+@@ -1837,13 +1509,12 @@ void LLVoiceClient::stateMachine()
+ {
+ requestVoiceAccountProvision();
+ }
+- setState(stateConnectorStart);
++ setState(stateNeedsLogin);
+ }
+ }
+ }
+ break;
+-
+- //MARK: stateMicTuningStart
++
+ case stateMicTuningStart:
+ if(mUpdateTimer.hasExpired())
+ {
+@@ -1851,9 +1522,19 @@ void LLVoiceClient::stateMachine()
+ {
+ // These can't be changed while in tuning mode. Set them before starting.
+ std::ostringstream stream;
+-
+- buildSetCaptureDevice(stream);
+- buildSetRenderDevice(stream);
++
++ if(mCaptureDeviceDirty)
++ {
++ buildSetCaptureDevice(stream);
++ }
++
++ if(mRenderDeviceDirty)
++ {
++ buildSetRenderDevice(stream);
++ }
++
++ mCaptureDeviceDirty = false;
++ mRenderDeviceDirty = false;
+
+ if(!stream.str().empty())
+ {
+@@ -1875,9 +1556,8 @@ void LLVoiceClient::stateMachine()
+
+ break;
+
+- //MARK: stateMicTuningRunning
+ case stateMicTuningRunning:
+- if(!mTuningMode || mCaptureDeviceDirty || mRenderDeviceDirty)
++ if(!mTuningMode || !mVoiceEnabled || mSessionTerminateRequested || mCaptureDeviceDirty || mRenderDeviceDirty)
+ {
+ // All of these conditions make us leave tuning mode.
+ setState(stateMicTuningStop);
+@@ -1917,7 +1597,6 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateMicTuningStop
+ case stateMicTuningStop:
+ {
+ // transition out of mic tuning
+@@ -1931,40 +1610,7 @@ void LLVoiceClient::stateMachine()
+
+ }
+ break;
+-
+- //MARK: stateConnectorStart
+- case stateConnectorStart:
+- if(!mVoiceEnabled)
+- {
+- // We were never logged in. This will shut down the connector.
+- setState(stateLoggedOut);
+- }
+- else if(!mVoiceAccountServerURI.empty())
+- {
+- connectorCreate();
+- }
+- break;
+-
+- //MARK: stateConnectorStarting
+- case stateConnectorStarting: // waiting for connector handle
+- // connectorCreateResponse() will transition from here to stateConnectorStarted.
+- break;
+-
+- //MARK: stateConnectorStarted
+- case stateConnectorStarted: // connector handle received
+- if(!mVoiceEnabled)
+- {
+- // We were never logged in. This will shut down the connector.
+- setState(stateLoggedOut);
+- }
+- else
+- {
+- // The connector is started. Send a login message.
+- setState(stateNeedsLogin);
+- }
+- break;
+-
+- //MARK: stateLoginRetry
++
+ case stateLoginRetry:
+ if(mLoginRetryCount == 0)
+ {
+@@ -1988,7 +1634,6 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateLoginRetryWait
+ case stateLoginRetryWait:
+ if(mUpdateTimer.hasExpired())
+ {
+@@ -1996,7 +1641,6 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateNeedsLogin
+ case stateNeedsLogin:
+ if(!mAccountPassword.empty())
+ {
+@@ -2005,22 +1649,16 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateLoggingIn
+ case stateLoggingIn: // waiting for account handle
+ // loginResponse() will transition from here to stateLoggedIn.
+ break;
+
+- //MARK: stateLoggedIn
+ case stateLoggedIn: // account handle received
++ // Initial kick-off of channel lookup logic
++ parcelChanged();
+
+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
+
+- // request the current set of block rules (we'll need them when updating the friends list)
+- accountListBlockRulesSendMessage();
+-
+- // request the current set of auto-accept rules
+- accountListAutoAcceptRulesSendMessage();
+-
+ // Set up the mute list observer if it hasn't been set up already.
+ if((!sMuteListListener_listening))
+ {
+@@ -2028,67 +1666,13 @@ void LLVoiceClient::stateMachine()
+ sMuteListListener_listening = true;
+ }
+
+- // Set up the friends list observer if it hasn't been set up already.
+- if(friendslist_listener == NULL)
+- {
+- friendslist_listener = new LLVoiceClientFriendsObserver;
+- LLAvatarTracker::instance().addObserver(friendslist_listener);
+- }
+-
+- // Set the initial state of mic mute, local speaker volume, etc.
+- {
+- std::ostringstream stream;
+-
+- buildLocalAudioUpdates(stream);
+-
+- if(!stream.str().empty())
+- {
+- writeString(stream.str());
+- }
+- }
+-
+-#if USE_SESSION_GROUPS
+- // create the main session group
+- sessionGroupCreateSendMessage();
+-
+- setState(stateCreatingSessionGroup);
+-#else
+- // Not using session groups -- skip the stateCreatingSessionGroup state.
+ setState(stateNoChannel);
+-
+- // Initial kick-off of channel lookup logic
+- parcelChanged();
+-#endif
+- break;
+-
+- //MARK: stateCreatingSessionGroup
+- case stateCreatingSessionGroup:
+- if(mSessionTerminateRequested || !mVoiceEnabled)
+- {
+- // TODO: Question: is this the right way out of this state
+- setState(stateSessionTerminated);
+- }
+- else if(!mMainSessionGroupHandle.empty())
+- {
+- setState(stateNoChannel);
+-
+- // Start looped recording (needed for "panic button" anti-griefing tool)
+- recordingLoopStart();
+-
+- // Initial kick-off of channel lookup logic
+- parcelChanged();
+- }
+ break;
+
+- //MARK: stateNoChannel
+ case stateNoChannel:
+- // Do this here as well as inside sendPositionalUpdate().
+- // Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
+- sendFriendsListUpdates();
+-
+ if(mSessionTerminateRequested || !mVoiceEnabled)
+ {
+- // TODO: Question: Is this the right way out of this state?
++ // MBW -- XXX -- Is this the right way out of this state?
+ setState(stateSessionTerminated);
+ }
+ else if(mTuningMode)
+@@ -2096,49 +1680,30 @@ void LLVoiceClient::stateMachine()
+ mTuningExitState = stateNoChannel;
+ setState(stateMicTuningStart);
+ }
+- else if(sessionNeedsRelog(mNextAudioSession))
++ else if(!mNextSessionHandle.empty())
+ {
+- requestRelog();
+- setState(stateSessionTerminated);
++ setState(stateSessionConnect);
+ }
+- else if(mNextAudioSession)
+- {
+- sessionState *oldSession = mAudioSession;
+-
+- mAudioSession = mNextAudioSession;
+- if(!mAudioSession->mReconnect)
+- {
+- mNextAudioSession = NULL;
+- }
+-
+- // The old session may now need to be deleted.
+- reapSession(oldSession);
+-
+- if(!mAudioSession->mHandle.empty())
+- {
+- // Connect to a session by session handle
+-
+- sessionMediaConnectSendMessage(mAudioSession);
+- }
+- else
+- {
+- // Connect to a session by URI
+- sessionCreateSendMessage(mAudioSession, true, false);
+- }
+-
+- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
+- setState(stateJoiningSession);
+- }
+- else if(!mSpatialSessionURI.empty())
++ else if(!mNextSessionURI.empty())
+ {
+- // If we're not headed elsewhere and have a spatial URI, return to spatial.
+- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
++ setState(stateSessionCreate);
+ }
+ break;
+
+- //MARK: stateJoiningSession
++ case stateSessionCreate:
++ sessionCreateSendMessage();
++ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
++ setState(stateJoiningSession);
++ break;
++
++ case stateSessionConnect:
++ sessionConnectSendMessage();
++ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
++ setState(stateJoiningSession);
++ break;
++
+ case stateJoiningSession: // waiting for session handle
+- // joinedAudioSession() will transition from here to stateSessionJoined.
++ // sessionCreateResponse() will transition from here to stateSessionJoined.
+ if(!mVoiceEnabled)
+ {
+ // User bailed out during connect -- jump straight to teardown.
+@@ -2146,27 +1711,30 @@ void LLVoiceClient::stateMachine()
+ }
+ else if(mSessionTerminateRequested)
+ {
+- if(mAudioSession && !mAudioSession->mHandle.empty())
++ if(!mSessionHandle.empty())
+ {
+ // Only allow direct exits from this state in p2p calls (for cancelling an invite).
+ // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
+- if(mAudioSession->mIsP2P)
++ if(mSessionP2P)
+ {
+- sessionMediaDisconnectSendMessage(mAudioSession);
++ sessionTerminateSendMessage();
+ setState(stateSessionTerminated);
+ }
+ }
+ }
+ break;
+
+- //MARK: stateSessionJoined
+ case stateSessionJoined: // session handle received
+- // It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
+- // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
+- // For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
++ // MBW -- XXX -- It appears that I need to wait for BOTH the Session.Create response and the SessionStateChangeEvent with state 4
++ // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
++ // For now, the Session.Create response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
+ // This is a cheap way to make sure both have happened before proceeding.
+- if(mAudioSession && mAudioSession->mVoiceEnabled)
++ if(!mSessionHandle.empty())
+ {
++ // Events that need to happen when a session is joined could go here.
++ // Maybe send initial spatial data?
++ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
++
+ // Dirty state that may need to be sync'ed with the daemon.
+ mPTTDirty = true;
+ mSpeakerVolumeDirty = true;
+@@ -2177,11 +1745,6 @@ void LLVoiceClient::stateMachine()
+ // Start the throttle timer
+ mUpdateTimer.start();
+ mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+-
+- // Events that need to happen when a session is joined could go here.
+- // Maybe send initial spatial data?
+- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
+-
+ }
+ else if(!mVoiceEnabled)
+ {
+@@ -2192,20 +1755,21 @@ void LLVoiceClient::stateMachine()
+ {
+ // Only allow direct exits from this state in p2p calls (for cancelling an invite).
+ // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
+- if(mAudioSession && mAudioSession->mIsP2P)
++ if(mSessionP2P)
+ {
+- sessionMediaDisconnectSendMessage(mAudioSession);
++ sessionTerminateSendMessage();
+ setState(stateSessionTerminated);
+ }
+ }
+ break;
+
+- //MARK: stateRunning
+ case stateRunning: // steady state
++ // sessionTerminateSendMessage() will transition from here to stateLeavingSession
++
+ // Disabling voice or disconnect requested.
+ if(!mVoiceEnabled || mSessionTerminateRequested)
+ {
+- leaveAudioSession();
++ sessionTerminateSendMessage();
+ }
+ else
+ {
+@@ -2238,7 +1802,7 @@ void LLVoiceClient::stateMachine()
+ }
+ }
+
+- if(!inSpatialChannel())
++ if(mNonSpatialChannel)
+ {
+ // When in a non-spatial channel, never send positional updates.
+ mSpatialCoordsDirty = false;
+@@ -2251,7 +1815,7 @@ void LLVoiceClient::stateMachine()
+
+ // Send an update if the ptt state has changed (which shouldn't be able to happen that often -- the user can only click so fast)
+ // or every 10hz, whichever is sooner.
+- if((mAudioSession && mAudioSession->mVolumeDirty) || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
++ if(mVolumeDirty || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
+ {
+ mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
+ sendPositionalUpdate();
+@@ -2259,38 +1823,25 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateLeavingSession
+ case stateLeavingSession: // waiting for terminate session response
+ // The handler for the Session.Terminate response will transition from here to stateSessionTerminated.
+ break;
+
+- //MARK: stateSessionTerminated
+ case stateSessionTerminated:
++ // Always reset the terminate request flag when we get here.
++ mSessionTerminateRequested = false;
+
+- // Must do this first, since it uses mAudioSession.
+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
+-
+- if(mAudioSession)
+- {
+- sessionState *oldSession = mAudioSession;
+
+- mAudioSession = NULL;
+- // We just notified status observers about this change. Don't do it again.
+- mAudioSessionChanged = false;
+-
+- // The old session may now need to be deleted.
+- reapSession(oldSession);
+- }
+- else
++ if(mVoiceEnabled)
+ {
+- LL_WARNS("Voice") << "stateSessionTerminated with NULL mAudioSession" << LL_ENDL;
+- }
+-
+- // Always reset the terminate request flag when we get here.
+- mSessionTerminateRequested = false;
+-
+- if(mVoiceEnabled && !mRelogRequested)
+- {
++ // SPECIAL CASE: if going back to spatial but in a parcel with an empty URI, transfer the non-spatial flag now.
++ // This fixes the case where you come out of a group chat in a parcel with voice disabled, and get stuck unable to rejoin spatial chat thereafter.
++ if(mNextSessionSpatial && mNextSessionURI.empty())
++ {
++ mNonSpatialChannel = !mNextSessionSpatial;
++ }
++
+ // Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state).
+ setState(stateNoChannel);
+ }
+@@ -2298,67 +1849,49 @@ void LLVoiceClient::stateMachine()
+ {
+ // Shutting down voice, continue with disconnecting.
+ logout();
+-
+- // The state machine will take it from here
+- mRelogRequested = false;
+ }
+
+ break;
+
+- //MARK: stateLoggingOut
+ case stateLoggingOut: // waiting for logout response
+ // The handler for the Account.Logout response will transition from here to stateLoggedOut.
+ break;
+- //MARK: stateLoggedOut
+ case stateLoggedOut: // logout response received
+ // shut down the connector
+ connectorShutdown();
+ break;
+
+- //MARK: stateConnectorStopping
+ case stateConnectorStopping: // waiting for connector stop
+ // The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped.
+ break;
+
+- //MARK: stateConnectorStopped
+ case stateConnectorStopped: // connector stop received
+- setState(stateDisableCleanup);
++ // Clean up and reset everything.
++ closeSocket();
++ removeAllParticipants();
++ setState(stateDisabled);
+ break;
+
+- //MARK: stateConnectorFailed
+ case stateConnectorFailed:
+ setState(stateConnectorFailedWaiting);
+ break;
+- //MARK: stateConnectorFailedWaiting
+ case stateConnectorFailedWaiting:
+ break;
+
+- //MARK: stateLoginFailed
+ case stateLoginFailed:
+ setState(stateLoginFailedWaiting);
+ break;
+- //MARK: stateLoginFailedWaiting
+ case stateLoginFailedWaiting:
+ // No way to recover from these. Yet.
+ break;
+
+- //MARK: stateJoinSessionFailed
+ case stateJoinSessionFailed:
+ // Transition to error state. Send out any notifications here.
+- if(mAudioSession)
+- {
+- LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mAudioSession->mErrorStatusCode << "): " << mAudioSession->mErrorStatusString << LL_ENDL;
+- }
+- else
+- {
+- LL_WARNS("Voice") << "stateJoinSessionFailed with no current session" << LL_ENDL;
+- }
+-
++ LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mVivoxErrorStatusCode << "): " << mVivoxErrorStatusString << LL_ENDL;
+ notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
+ setState(stateJoinSessionFailedWaiting);
+ break;
+
+- //MARK: stateJoinSessionFailedWaiting
+ case stateJoinSessionFailedWaiting:
+ // Joining a channel failed, either due to a failed channel name -> sip url lookup or an error from the join message.
+ // Region crossings may leave this state and try the join again.
+@@ -2368,24 +1901,22 @@ void LLVoiceClient::stateMachine()
+ }
+ break;
+
+- //MARK: stateJail
+ case stateJail:
+ // We have given up. Do nothing.
+ break;
+
++ case stateMicTuningNoLogin:
++ // *TODO: Implement me.
++ LL_WARNS("Voice") << "stateMicTuningNoLogin not handled" << LL_ENDL;
++ break;
+ }
+-
+- if(mAudioSession && mAudioSession->mParticipantsChanged)
+- {
+- mAudioSession->mParticipantsChanged = false;
+- mAudioSessionChanged = true;
+- }
+-
+- if(mAudioSessionChanged)
++
++ if(mParticipantMapChanged)
+ {
+- mAudioSessionChanged = false;
+- notifyParticipantObservers();
++ mParticipantMapChanged = false;
++ notifyObservers();
+ }
++
+ }
+
+ void LLVoiceClient::closeSocket(void)
+@@ -2403,9 +1934,6 @@ void LLVoiceClient::loginSendMessage()
+ << "" << mAccountName << ""
+ << "" << mAccountPassword << ""
+ << "VerifyAnswer"
+- << "true"
+- << "Application"
+- << "5"
+ << "\n\n\n";
+
+ writeString(stream.str());
+@@ -2413,10 +1941,7 @@ void LLVoiceClient::loginSendMessage()
+
+ void LLVoiceClient::logout()
+ {
+- // Ensure that we'll re-request provisioning before logging in again
+- mAccountPassword.clear();
+- mVoiceAccountServerURI.clear();
+-
++ mAccountPassword = "";
+ setState(stateLoggingOut);
+ logoutSendMessage();
+ }
+@@ -2438,164 +1963,78 @@ void LLVoiceClient::logoutSendMessage()
+ }
+ }
+
+-void LLVoiceClient::accountListBlockRulesSendMessage()
++void LLVoiceClient::channelGetListSendMessage()
+ {
+- if(!mAccountHandle.empty())
+- {
+- std::ostringstream stream;
+-
+- LL_DEBUGS("Voice") << "requesting block rules" << LL_ENDL;
+-
+- stream
+- << ""
+- << "" << mAccountHandle << ""
+- << ""
+- << "\n\n\n";
+-
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::accountListAutoAcceptRulesSendMessage()
+-{
+- if(!mAccountHandle.empty())
+- {
+- std::ostringstream stream;
+-
+- LL_DEBUGS("Voice") << "requesting auto-accept rules" << LL_ENDL;
+-
+- stream
+- << ""
+- << "" << mAccountHandle << ""
+- << ""
+- << "\n\n\n";
++ std::ostringstream stream;
++ stream
++ << ""
++ << "" << mAccountHandle << ""
++ << "\n\n\n";
+
+- writeString(stream.str());
+- }
++ writeString(stream.str());
+ }
+
+-void LLVoiceClient::sessionGroupCreateSendMessage()
++void LLVoiceClient::sessionCreateSendMessage()
+ {
+- if(!mAccountHandle.empty())
+- {
+- std::ostringstream stream;
+-
+- LL_DEBUGS("Voice") << "creating session group" << LL_ENDL;
++ LL_DEBUGS("Voice") << "requesting join: " << mNextSessionURI << LL_ENDL;
+
+- stream
+- << ""
+- << "" << mAccountHandle << ""
+- << "Normal"
+- << ""
+- << "\n\n\n";
+-
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)
+-{
+- LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
+-
+- session->mCreateInProgress = true;
+- if(startAudio)
++ mSessionURI = mNextSessionURI;
++ mNonSpatialChannel = !mNextSessionSpatial;
++ mSessionResetOnClose = mNextSessionResetOnClose;
++ mNextSessionResetOnClose = false;
++ if(mNextSessionNoReconnect)
+ {
+- session->mMediaConnectInProgress = true;
++ // Clear the stashed URI so it can't reconnect
++ mNextSessionURI.clear();
+ }
++ // Only p2p sessions are created with "no reconnect".
++ mSessionP2P = mNextSessionNoReconnect;
+
+ std::ostringstream stream;
+ stream
+- << "mSIPURI << "\" action=\"Session.Create.1\">"
++ << ""
+ << "" << mAccountHandle << ""
+- << "" << session->mSIPURI << "";
++ << "" << mSessionURI << "";
+
+ static const std::string allowed_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "-._~";
+
+- if(!session->mHash.empty())
++ if(!mNextSessionHash.empty())
+ {
+ stream
+- << "" << LLURI::escape(session->mHash, allowed_chars) << ""
++ << "" << LLURI::escape(mNextSessionHash, allowed_chars) << ""
+ << "SHA1UserName";
+ }
+
+ stream
+- << "" << (startAudio?"true":"false") << ""
+- << "" << (startText?"true":"false") << ""
+ << "" << mChannelName << ""
+ << "\n\n\n";
+ writeString(stream.str());
+ }
+
+-void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)
++void LLVoiceClient::sessionConnectSendMessage()
+ {
+- LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
+-
+- session->mCreateInProgress = true;
+- if(startAudio)
+- {
+- session->mMediaConnectInProgress = true;
+- }
+-
+- std::string password;
+- if(!session->mHash.empty())
+- {
+- static const std::string allowed_chars =
+- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+- "0123456789"
+- "-._~"
+- ;
+- password = LLURI::escape(session->mHash, allowed_chars);
+- }
+-
+- std::ostringstream stream;
+- stream
+- << "mSIPURI << "\" action=\"SessionGroup.AddSession.1\">"
+- << "" << session->mGroupHandle << ""
+- << "" << session->mSIPURI << ""
+- << "" << mChannelName << ""
+- << "" << (startAudio?"true":"false") << ""
+- << "" << (startText?"true":"false") << ""
+- << "" << password << ""
+- << "SHA1UserName"
+- << "\n\n\n"
+- ;
++ LL_DEBUGS("Voice") << "connecting to session handle: " << mNextSessionHandle << LL_ENDL;
+
+- writeString(stream.str());
+-}
+-
+-void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
+-{
+- LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL;
+-
+- session->mMediaConnectInProgress = true;
++ mSessionHandle = mNextSessionHandle;
++ mSessionURI = mNextP2PSessionURI;
++ mNextSessionHandle.clear(); // never want to re-use these.
++ mNextP2PSessionURI.clear();
++ mNonSpatialChannel = !mNextSessionSpatial;
++ mSessionResetOnClose = mNextSessionResetOnClose;
++ mNextSessionResetOnClose = false;
++ // Joining by session ID is only used to answer p2p invitations, so we know this is a p2p session.
++ mSessionP2P = true;
+
+ std::ostringstream stream;
+-
+- stream
+- << "mHandle << "\" action=\"Session.MediaConnect.1\">"
+- << "" << session->mGroupHandle << ""
+- << "" << session->mHandle << ""
+- << "Audio"
+- << "\n\n\n";
+-
+- writeString(stream.str());
+-}
+-
+-void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
+-{
+- LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL;
+
+- std::ostringstream stream;
+-
+ stream
+- << "mHandle << "\" action=\"Session.TextConnect.1\">"
+- << "" << session->mGroupHandle << ""
+- << "" << session->mHandle << ""
++ << ""
++ << "" << mSessionHandle << ""
++ << "default"
+ << "\n\n\n";
+-
+ writeString(stream.str());
+ }
+
+@@ -2604,112 +2043,52 @@ void LLVoiceClient::sessionTerminate()
+ mSessionTerminateRequested = true;
+ }
+
+-void LLVoiceClient::requestRelog()
++void LLVoiceClient::sessionTerminateSendMessage()
+ {
+- mSessionTerminateRequested = true;
+- mRelogRequested = true;
+-}
++ LL_DEBUGS("Voice") << "leaving session: " << mSessionURI << LL_ENDL;
+
+-
+-void LLVoiceClient::leaveAudioSession()
+-{
+- if(mAudioSession)
++ switch(getState())
+ {
+- LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL;
+-
+- switch(getState())
+- {
+- case stateNoChannel:
+- // In this case, we want to pretend the join failed so our state machine doesn't get stuck.
+- // Skip the join failed transition state so we don't send out error notifications.
+- setState(stateJoinSessionFailedWaiting);
+- break;
+- case stateJoiningSession:
+- case stateSessionJoined:
+- case stateRunning:
+- if(!mAudioSession->mHandle.empty())
+- {
+-
+-#if RECORD_EVERYTHING
+- // HACK: for testing only
+- // Save looped recording
+- std::string savepath("/tmp/vivoxrecording");
+- {
+- time_t now = time(NULL);
+- const size_t BUF_SIZE = 64;
+- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
+-
+- strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
+- savepath += time_str;
+- }
+- recordingLoopSave(savepath);
+-#endif
+-
+- sessionMediaDisconnectSendMessage(mAudioSession);
+- setState(stateLeavingSession);
+- }
+- else
+- {
+- LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
+- setState(stateSessionTerminated);
+- }
+- break;
+- case stateJoinSessionFailed:
+- case stateJoinSessionFailedWaiting:
++ case stateNoChannel:
++ // In this case, we want to pretend the join failed so our state machine doesn't get stuck.
++ // Skip the join failed transition state so we don't send out error notifications.
++ setState(stateJoinSessionFailedWaiting);
++ break;
++ case stateJoiningSession:
++ case stateSessionJoined:
++ case stateRunning:
++ if(!mSessionHandle.empty())
++ {
++ sessionTerminateByHandle(mSessionHandle);
++ setState(stateLeavingSession);
++ }
++ else
++ {
++ LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
+ setState(stateSessionTerminated);
+- break;
+-
+- default:
+- LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
+- break;
+- }
+- }
+- else
+- {
+- LL_WARNS("Voice") << "called with no active session" << LL_ENDL;
+- setState(stateSessionTerminated);
++ }
++ break;
++ case stateJoinSessionFailed:
++ case stateJoinSessionFailedWaiting:
++ setState(stateSessionTerminated);
++ break;
++
++ default:
++ LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
++ break;
+ }
+ }
+
+-void LLVoiceClient::sessionTerminateSendMessage(sessionState *session)
++void LLVoiceClient::sessionTerminateByHandle(std::string &sessionHandle)
+ {
+- std::ostringstream stream;
+-
+- LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL;
+- stream
+- << ""
+- << "" << session->mHandle << ""
+- << "\n\n\n";
+-
+- writeString(stream.str());
+-}
++ LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << sessionHandle << LL_ENDL;
+
+-void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session)
+-{
+ std::ostringstream stream;
+-
+- LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL;
+ stream
+- << ""
+- << "" << session->mGroupHandle << ""
+- << "" << session->mHandle << ""
+- << "Audio"
+- << "\n\n\n";
+-
+- writeString(stream.str());
+-
+-}
+-
+-void LLVoiceClient::sessionTextDisconnectSendMessage(sessionState *session)
+-{
+- std::ostringstream stream;
+-
+- LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL;
+- stream
+- << ""
+- << "" << session->mGroupHandle << ""
+- << "" << session->mHandle << ""
+- << "\n\n\n";
++ << ""
++ << "" << sessionHandle << ""
++ << ""
++ << "\n\n\n";
+
+ writeString(stream.str());
+ }
+@@ -2736,12 +2115,14 @@ void LLVoiceClient::getRenderDevicesSendMessage()
+
+ void LLVoiceClient::clearCaptureDevices()
+ {
++ // MBW -- XXX -- do something here
+ LL_DEBUGS("Voice") << "called" << LL_ENDL;
+ mCaptureDevices.clear();
+ }
+
+ void LLVoiceClient::addCaptureDevice(const std::string& name)
+ {
++ // MBW -- XXX -- do something here
+ LL_DEBUGS("Voice") << name << LL_ENDL;
+
+ mCaptureDevices.push_back(name);
+@@ -2773,13 +2154,15 @@ void LLVoiceClient::setCaptureDevice(const std::string& name)
+ }
+
+ void LLVoiceClient::clearRenderDevices()
+-{
++{
++ // MBW -- XXX -- do something here
+ LL_DEBUGS("Voice") << "called" << LL_ENDL;
+ mRenderDevices.clear();
+ }
+
+ void LLVoiceClient::addRenderDevice(const std::string& name)
+ {
++ // MBW -- XXX -- do something here
+ LL_DEBUGS("Voice") << name << LL_ENDL;
+ mRenderDevices.push_back(name);
+ }
+@@ -2891,22 +2274,29 @@ void LLVoiceClient::tuningCaptureStopSendMessage()
+
+ void LLVoiceClient::tuningSetMicVolume(float volume)
+ {
+- int scaled_volume = scale_mic_volume(volume);
+-
+- if(scaled_volume != mTuningMicVolume)
++ int scaledVolume = ((int)(volume * 100.0f)) - 100;
++ if(scaledVolume != mTuningMicVolume)
+ {
+- mTuningMicVolume = scaled_volume;
++ mTuningMicVolume = scaledVolume;
+ mTuningMicVolumeDirty = true;
+ }
+ }
+
+ void LLVoiceClient::tuningSetSpeakerVolume(float volume)
+ {
+- int scaled_volume = scale_speaker_volume(volume);
++ // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
++ // Map it as follows: 0.0 -> -100, 0.5 -> 24, 1.0 -> 50
++
++ volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
++ int scaledVolume = 24; // offset scaledVolume by its default level
++ if(volume < 0.0f)
++ scaledVolume += ((int)(volume * 248.0f)); // (24 - (-100)) * 2
++ else
++ scaledVolume += ((int)(volume * 52.0f)); // (50 - 24) * 2
+
+- if(scaled_volume != mTuningSpeakerVolume)
++ if(scaledVolume != mTuningSpeakerVolume)
+ {
+- mTuningSpeakerVolume = scaled_volume;
++ mTuningSpeakerVolume = scaledVolume;
+ mTuningSpeakerVolumeDirty = true;
+ }
+ }
+@@ -2945,193 +2335,67 @@ void LLVoiceClient::daemonDied()
+ // The daemon died, so the connection is gone. Reset everything and start over.
+ LL_WARNS("Voice") << "Connection to vivox daemon lost. Resetting state."<< LL_ENDL;
+
++ closeSocket();
++ removeAllParticipants();
++
+ // Try to relaunch the daemon
+- setState(stateDisableCleanup);
++ setState(stateDisabled);
+ }
+
+ void LLVoiceClient::giveUp()
+ {
+ // All has failed. Clean up and stop trying.
+ closeSocket();
+- deleteAllSessions();
+- deleteAllBuddies();
++ removeAllParticipants();
+
+ setState(stateJail);
+ }
+
+-static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel)
+-{
+- F32 nat[3], nup[3], nl[3], nvel[3]; // the new at, up, left vectors and the new position and velocity
+- F64 npos[3];
+-
+- // The original XML command was sent like this:
+- /*
+- << ""
+- << "" << pos[VX] << ""
+- << "" << pos[VZ] << ""
+- << "" << pos[VY] << ""
+- << ""
+- << ""
+- << "" << mAvatarVelocity[VX] << ""
+- << "" << mAvatarVelocity[VZ] << ""
+- << "" << mAvatarVelocity[VY] << ""
+- << ""
+- << ""
+- << "" << l.mV[VX] << ""
+- << "" << u.mV[VX] << ""
+- << "" << a.mV[VX] << ""
+- << ""
+- << ""
+- << "" << l.mV[VZ] << ""
+- << "" << u.mV[VY] << ""
+- << "" << a.mV[VZ] << ""
+- << ""
+- << ""
+- << "" << l.mV [VY] << ""
+- << "" << u.mV [VZ] << ""
+- << "" << a.mV [VY] << ""
+- << "";
+- */
+-
+-#if 1
+- // This was the original transform done when building the XML command
+- nat[0] = left.mV[VX];
+- nat[1] = up.mV[VX];
+- nat[2] = at.mV[VX];
+-
+- nup[0] = left.mV[VZ];
+- nup[1] = up.mV[VY];
+- nup[2] = at.mV[VZ];
+-
+- nl[0] = left.mV[VY];
+- nl[1] = up.mV[VZ];
+- nl[2] = at.mV[VY];
+-
+- npos[0] = pos.mdV[VX];
+- npos[1] = pos.mdV[VZ];
+- npos[2] = pos.mdV[VY];
+-
+- nvel[0] = vel.mV[VX];
+- nvel[1] = vel.mV[VZ];
+- nvel[2] = vel.mV[VY];
+-
+- for(int i=0;i<3;++i) {
+- at.mV[i] = nat[i];
+- up.mV[i] = nup[i];
+- left.mV[i] = nl[i];
+- pos.mdV[i] = npos[i];
+- }
+-
+- // This was the original transform done in the SDK
+- nat[0] = at.mV[2];
+- nat[1] = 0; // y component of at vector is always 0, this was up[2]
+- nat[2] = -1 * left.mV[2];
+-
+- // We override whatever the application gives us
+- nup[0] = 0; // x component of up vector is always 0
+- nup[1] = 1; // y component of up vector is always 1
+- nup[2] = 0; // z component of up vector is always 0
+-
+- nl[0] = at.mV[0];
+- nl[1] = 0; // y component of left vector is always zero, this was up[0]
+- nl[2] = -1 * left.mV[0];
+-
+- npos[2] = pos.mdV[2] * -1.0;
+- npos[1] = pos.mdV[1];
+- npos[0] = pos.mdV[0];
+-
+- for(int i=0;i<3;++i) {
+- at.mV[i] = nat[i];
+- up.mV[i] = nup[i];
+- left.mV[i] = nl[i];
+- pos.mdV[i] = npos[i];
+- }
+-#else
+- // This is the compose of the two transforms (at least, that's what I'm trying for)
+- nat[0] = at.mV[VX];
+- nat[1] = 0; // y component of at vector is always 0, this was up[2]
+- nat[2] = -1 * up.mV[VZ];
+-
+- // We override whatever the application gives us
+- nup[0] = 0; // x component of up vector is always 0
+- nup[1] = 1; // y component of up vector is always 1
+- nup[2] = 0; // z component of up vector is always 0
+-
+- nl[0] = left.mV[VX];
+- nl[1] = 0; // y component of left vector is always zero, this was up[0]
+- nl[2] = -1 * left.mV[VY];
+-
+- npos[0] = pos.mdV[VX];
+- npos[1] = pos.mdV[VZ];
+- npos[2] = pos.mdV[VY] * -1.0;
+-
+- nvel[0] = vel.mV[VX];
+- nvel[1] = vel.mV[VZ];
+- nvel[2] = vel.mV[VY];
+-
+- for(int i=0;i<3;++i) {
+- at.mV[i] = nat[i];
+- up.mV[i] = nup[i];
+- left.mV[i] = nl[i];
+- pos.mdV[i] = npos[i];
+- }
+-
+-#endif
+-}
+-
+ void LLVoiceClient::sendPositionalUpdate(void)
+ {
+ std::ostringstream stream;
+
+ if(mSpatialCoordsDirty)
+ {
+- LLVector3 l, u, a, vel;
+- LLVector3d pos;
+-
+- mSpatialCoordsDirty = false;
++ LLVector3 l, u, a;
+
+ // Always send both speaker and listener positions together.
+ stream << ""
+- << "" << getAudioSessionHandle() << "";
++ << "" << mSessionHandle << "";
+
+ stream << "";
+
+-// LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
+ l = mAvatarRot.getLeftRow();
+ u = mAvatarRot.getUpRow();
+ a = mAvatarRot.getFwdRow();
+- pos = mAvatarPosition;
+- vel = mAvatarVelocity;
++
++ LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
+
+- // SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore.
+- // The old transform is replicated by this function.
+- oldSDKTransform(l, u, a, pos, vel);
+-
+ stream
+ << ""
+- << "" << pos.mdV[VX] << ""
+- << "" << pos.mdV[VY] << ""
+- << "" << pos.mdV[VZ] << ""
++ << "" << mAvatarPosition[VX] << ""
++ << "" << mAvatarPosition[VZ] << ""
++ << "" << mAvatarPosition[VY] << ""
+ << ""
+ << ""
+- << "" << vel.mV[VX] << ""
+- << "" << vel.mV[VY] << ""
+- << "" << vel.mV[VZ] << ""
++ << "" << mAvatarVelocity[VX] << ""
++ << "" << mAvatarVelocity[VZ] << ""
++ << "" << mAvatarVelocity[VY] << ""
+ << ""
+ << ""
+- << "" << a.mV[VX] << ""
+- << "" << a.mV[VY] << ""
+- << "" << a.mV[VZ] << ""
++ << "" << l.mV[VX] << ""
++ << "" << u.mV[VX] << ""
++ << "" << a.mV[VX] << ""
+ << ""
+ << ""
+- << "" << u.mV[VX] << ""
++ << "" << l.mV[VZ] << ""
+ << "" << u.mV[VY] << ""
+- << "" << u.mV[VZ] << ""
++ << "" << a.mV[VZ] << ""
+ << ""
+ << ""
+- << "" << l.mV [VX] << ""
+- << "" << l.mV [VY] << ""
+- << "" << l.mV [VZ] << ""
++ << "" << l.mV [VY] << ""
++ << "" << u.mV [VZ] << ""
++ << "" << a.mV [VY] << ""
+ << "";
+
+ stream << "";
+@@ -3167,158 +2431,43 @@ void LLVoiceClient::sendPositionalUpdate(void)
+ l = earRot.getLeftRow();
+ u = earRot.getUpRow();
+ a = earRot.getFwdRow();
+- pos = earPosition;
+- vel = earVelocity;
+
+-// LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
+-
+- oldSDKTransform(l, u, a, pos, vel);
+-
++ LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
++
+ stream
+ << ""
+- << "" << pos.mdV[VX] << ""
+- << "" << pos.mdV[VY] << ""
+- << "" << pos.mdV[VZ] << ""
++ << "" << earPosition[VX] << ""
++ << "" << earPosition[VZ] << ""
++ << "" << earPosition[VY] << ""
+ << ""
+ << ""
+- << "" << vel.mV[VX] << ""
+- << "" << vel.mV[VY] << ""
+- << "" << vel.mV[VZ] << ""
++ << "" << earVelocity[VX] << ""
++ << "" << earVelocity[VZ] << ""
++ << "" << earVelocity[VY] << ""
+ << ""
+ << ""
+- << "" << a.mV[VX] << ""
+- << "" << a.mV[VY] << ""
+- << "" << a.mV[VZ] << ""
++ << "" << l.mV[VX] << ""
++ << "" << u.mV[VX] << ""
++ << "" << a.mV[VX] << ""
+ << ""
+ << ""
+- << "" << u.mV[VX] << ""
++ << "" << l.mV[VZ] << ""
+ << "" << u.mV[VY] << ""
+- << "" << u.mV[VZ] << ""
++ << "" << a.mV[VZ] << ""
+ << ""
+ << ""
+- << "" << l.mV [VX] << ""
+- << "" << l.mV [VY] << ""
+- << "" << l.mV [VZ] << ""
++ << "" << l.mV [VY] << ""
++ << "" << u.mV [VZ] << ""
++ << "" << a.mV [VY] << ""
+ << "";
+
+-
+ stream << "";
+
+ stream << "\n\n\n";
+ }
+-
+- if(mAudioSession && mAudioSession->mVolumeDirty)
+- {
+- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
+-
+- mAudioSession->mVolumeDirty = false;
+-
+- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
+- {
+- participantState *p = iter->second;
+-
+- if(p->mVolumeDirty)
+- {
+- // Can't set volume/mute for yourself
+- if(!p->mIsSelf)
+- {
+- int volume = p->mUserVolume;
+- bool mute = p->mOnMuteList;
+-
+- // SLIM SDK: scale volume from 0-400 (with 100 as "normal") to 0-100 (with 56 as "normal")
+- if(volume < 100)
+- volume = (volume * 56) / 100;
+- else
+- volume = (((volume - 100) * (100 - 56)) / 300) + 56;
+-
+- if(mute)
+- {
+- // SetParticipantMuteForMe doesn't work in p2p sessions.
+- // If we want the user to be muted, set their volume to 0 as well.
+- // This isn't perfect, but it will at least reduce their volume to a minimum.
+- volume = 0;
+- }
+-
+- if(volume == 0)
+- mute = true;
+-
+- LL_DEBUGS("Voice") << "Setting volume/mute for avatar " << p->mAvatarID << " to " << volume << (mute?"/true":"/false") << LL_ENDL;
+-
+- // SLIM SDK: Send both volume and mute commands.
+-
+- // Send a "volume for me" command for the user.
+- stream << ""
+- << "" << getAudioSessionHandle() << ""
+- << "" << p->mURI << ""
+- << "" << volume << ""
+- << "\n\n\n";
+-
+- // Send a "mute for me" command for the user
+- stream << ""
+- << "" << getAudioSessionHandle() << ""
+- << "" << p->mURI << ""
+- << "" << (mute?"1":"0") << ""
+- << "\n\n\n";
+- }
+-
+- p->mVolumeDirty = false;
+- }
+- }
+- }
+-
+- buildLocalAudioUpdates(stream);
+-
+- if(!stream.str().empty())
+- {
+- writeString(stream.str());
+- }
+-
+- // Friends list updates can be huge, especially on the first voice login of an account with lots of friends.
+- // Batching them all together can choke SLVoice, so send them in separate writes.
+- sendFriendsListUpdates();
+-}
+-
+-void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
+-{
+- if(mCaptureDeviceDirty)
+- {
+- LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
+-
+- stream
+- << ""
+- << "" << mCaptureDevice << ""
+- << ""
+- << "\n\n\n";
+-
+- mCaptureDeviceDirty = false;
+- }
+-}
+-
+-void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
+-{
+- if(mRenderDeviceDirty)
+- {
+- LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
+-
+- stream
+- << ""
+- << "" << mRenderDevice << ""
+- << ""
+- << "\n\n\n";
+- mRenderDeviceDirty = false;
+- }
+-}
+-
+-void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
+-{
+- buildSetCaptureDevice(stream);
+-
+- buildSetRenderDevice(stream);
+
+ if(mPTTDirty)
+ {
+- mPTTDirty = false;
+-
+ // Send a local mute command.
+ // NOTE that the state of "PTT" is the inverse of "local mute".
+ // (i.e. when PTT is true, we send a mute command with "false", and vice versa)
+@@ -3329,337 +2478,119 @@ void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
+ << "" << mConnectorHandle << ""
+ << "" << (mPTT?"false":"true") << ""
+ << "\n\n\n";
+-
++
+ }
++
++ if(mVolumeDirty)
++ {
++ participantMap::iterator iter = mParticipantMap.begin();
++
++ for(; iter != mParticipantMap.end(); iter++)
++ {
++ participantState *p = iter->second;
++
++ if(p->mVolumeDirty)
++ {
++ int volume = p->mOnMuteList?0:p->mUserVolume;
++
++ LL_INFOS("Voice") << "Setting volume for avatar " << p->mAvatarID << " to " << volume << LL_ENDL;
++
++ // Send a mute/unumte command for the user (actually "volume for me").
++ stream << ""
++ << "" << mSessionHandle << ""
++ << "" << p->mURI << ""
++ << "" << volume << ""
++ << "\n\n\n";
+
++ p->mVolumeDirty = false;
++ }
++ }
++ }
++
+ if(mSpeakerMuteDirty)
+ {
+- const char *muteval = ((mSpeakerVolume == 0)?"true":"false");
+-
+- mSpeakerMuteDirty = false;
+-
++ const char *muteval = ((mSpeakerVolume == -100)?"true":"false");
+ LL_INFOS("Voice") << "Setting speaker mute to " << muteval << LL_ENDL;
+
+ stream << ""
+ << "" << mConnectorHandle << ""
+ << "" << muteval << ""
+- << "\n\n\n";
+-
++ << "\n\n\n";
+ }
+
+ if(mSpeakerVolumeDirty)
+ {
+- mSpeakerVolumeDirty = false;
+-
+ LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume << LL_ENDL;
+
+ stream << ""
+ << "" << mConnectorHandle << ""
+ << "" << mSpeakerVolume << ""
+- << "\n\n\n";
+-
++ << "\n\n\n";
+ }
+
+ if(mMicVolumeDirty)
+ {
+- mMicVolumeDirty = false;
+-
+ LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume << LL_ENDL;
+
+ stream << ""
+ << "" << mConnectorHandle << ""
+ << "" << mMicVolume << ""
+- << "\n\n\n";
++ << "\n\n\n";
+ }
+
+
+-}
+-
+-void LLVoiceClient::checkFriend(const LLUUID& id)
+-{
+- std::string name;
+- buddyListEntry *buddy = findBuddy(id);
+-
+- // Make sure we don't add a name before it's been looked up.
+- if(gCacheName->getFullName(id, name))
++ // MBW -- XXX -- Maybe check to make sure the capture/render devices are in the current list here?
++ if(mCaptureDeviceDirty)
+ {
+-
+- const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
+- bool canSeeMeOnline = false;
+- if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
+- canSeeMeOnline = true;
+-
+- // When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary.
+-
+- if(buddy)
+- {
+- // This buddy is already in both lists.
+-
+- if(name != buddy->mDisplayName)
+- {
+- // The buddy is in the list with the wrong name. Update it with the correct name.
+- LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
+- buddy->mDisplayName = name;
+- buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
+- }
+- }
+- else
+- {
+- // This buddy was not in the vivox list, needs to be added.
+- buddy = addBuddy(sipURIFromID(id), name);
+- buddy->mUUID = id;
+- }
+-
+- // In all the above cases, the buddy is in the SL friends list (which is how we got here).
+- buddy->mInSLFriends = true;
+- buddy->mCanSeeMeOnline = canSeeMeOnline;
+- buddy->mNameResolved = true;
+-
++ buildSetCaptureDevice(stream);
+ }
+- else
++
++ if(mRenderDeviceDirty)
+ {
+- // This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has.
+- if(buddy)
+- {
+- buddy->mNameResolved = false;
+- }
+-
+- // Initiate a lookup.
+- // The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
+- lookupName(id);
++ buildSetRenderDevice(stream);
+ }
+-}
+-
+-void LLVoiceClient::clearAllLists()
+-{
+- // FOR TESTING ONLY
+
+- // This will send the necessary commands to delete ALL buddies, autoaccept rules, and block rules SLVoice tells us about.
+- buddyListMap::iterator buddy_it;
+- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
++ mSpatialCoordsDirty = false;
++ mPTTDirty = false;
++ mVolumeDirty = false;
++ mSpeakerVolumeDirty = false;
++ mMicVolumeDirty = false;
++ mSpeakerMuteDirty = false;
++ mCaptureDeviceDirty = false;
++ mRenderDeviceDirty = false;
++
++ if(!stream.str().empty())
+ {
+- buddyListEntry *buddy = buddy_it->second;
+- buddy_it++;
+-
+- std::ostringstream stream;
+-
+- if(buddy->mInVivoxBuddies)
+- {
+- // delete this entry from the vivox buddy list
+- buddy->mInVivoxBuddies = false;
+- LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+- }
+-
+- if(buddy->mHasBlockListEntry)
+- {
+- // Delete the associated block list entry (so the block list doesn't fill up with junk)
+- buddy->mHasBlockListEntry = false;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+- }
+- if(buddy->mHasAutoAcceptListEntry)
+- {
+- // Delete the associated auto-accept list entry (so the auto-accept list doesn't fill up with junk)
+- buddy->mHasAutoAcceptListEntry = false;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+- }
+-
+ writeString(stream.str());
+-
+ }
+ }
+
+-void LLVoiceClient::sendFriendsListUpdates()
++void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
+ {
+- if(mBuddyListMapPopulated && mBlockRulesListReceived && mAutoAcceptRulesListReceived && mFriendsListDirty)
+- {
+- mFriendsListDirty = false;
+-
+- if(0)
+- {
+- // FOR TESTING ONLY -- clear all buddy list, block list, and auto-accept list entries.
+- clearAllLists();
+- return;
+- }
+-
+- LL_INFOS("Voice") << "Checking vivox buddy list against friends list..." << LL_ENDL;
+-
+- buddyListMap::iterator buddy_it;
+- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
+- {
+- // reset the temp flags in the local buddy list
+- buddy_it->second->mInSLFriends = false;
+- }
+-
+- // correlate with the friends list
+- {
+- LLCollectAllBuddies collect;
+- LLAvatarTracker::instance().applyFunctor(collect);
+- LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin();
+- LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
+-
+- for ( ; it != end; ++it)
+- {
+- checkFriend(it->second);
+- }
+- it = collect.mOffline.begin();
+- end = collect.mOffline.end();
+- for ( ; it != end; ++it)
+- {
+- checkFriend(it->second);
+- }
+- }
+-
+- LL_INFOS("Voice") << "Sending friend list updates..." << LL_ENDL;
+-
+- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
+- {
+- buddyListEntry *buddy = buddy_it->second;
+- buddy_it++;
+-
+- // Ignore entries that aren't resolved yet.
+- if(buddy->mNameResolved)
+- {
+- std::ostringstream stream;
+-
+- if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
+- {
+- if(mNumberOfAliases > 0)
+- {
+- // Add (or update) this entry in the vivox buddy list
+- buddy->mInVivoxBuddies = true;
+- buddy->mNeedsNameUpdate = false;
+- LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
+- stream
+- << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "" << buddy->mDisplayName << ""
+- << "" // Without this, SLVoice doesn't seem to parse the command.
+- << "0"
+- << "\n\n\n";
+- }
+- }
+- else if(!buddy->mInSLFriends)
+- {
+- // This entry no longer exists in your SL friends list. Remove all traces of it from the Vivox buddy list.
+- if(buddy->mInVivoxBuddies)
+- {
+- // delete this entry from the vivox buddy list
+- buddy->mInVivoxBuddies = false;
+- LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+- }
+-
+- if(buddy->mHasBlockListEntry)
+- {
+- // Delete the associated block list entry, if any
+- buddy->mHasBlockListEntry = false;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+- }
+- if(buddy->mHasAutoAcceptListEntry)
+- {
+- // Delete the associated auto-accept list entry, if any
+- buddy->mHasAutoAcceptListEntry = false;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+- }
+- }
+-
+- if(buddy->mInSLFriends)
+- {
+-
+- if(buddy->mCanSeeMeOnline)
+- {
+- // Buddy should not be blocked.
+-
+- // If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
+-
+- // If the buddy has a block list entry, delete it.
+- if(buddy->mHasBlockListEntry)
+- {
+- buddy->mHasBlockListEntry = false;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+-
+-
+- // If we just deleted a block list entry, add an auto-accept entry.
+- if(!buddy->mHasAutoAcceptListEntry)
+- {
+- buddy->mHasAutoAcceptListEntry = true;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "0"
+- << "\n\n\n";
+- }
+- }
+- }
+- else
+- {
+- // Buddy should be blocked.
+-
+- // If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
+-
+- // If this buddy has an autoaccept entry, delete it
+- if(buddy->mHasAutoAcceptListEntry)
+- {
+- buddy->mHasAutoAcceptListEntry = false;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "\n\n\n";
+-
+- // If we just deleted an auto-accept entry, add a block list entry.
+- if(!buddy->mHasBlockListEntry)
+- {
+- buddy->mHasBlockListEntry = true;
+- stream << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "1"
+- << "\n\n\n";
+- }
+- }
+- }
++ LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
++
++ stream
++ << ""
++ << "" << mCaptureDevice << ""
++ << ""
++ << "\n\n\n";
++}
+
+- if(!buddy->mInSLFriends && !buddy->mInVivoxBuddies)
+- {
+- // Delete this entry from the local buddy list. This should NOT invalidate the iterator,
+- // since it has already been incremented to the next entry.
+- deleteBuddy(buddy->mURI);
+- }
++void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
++{
++ LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
+
+- }
+- writeString(stream.str());
+- }
+- }
+- }
++ stream
++ << ""
++ << "" << mRenderDevice << ""
++ << ""
++ << "\n\n\n";
+ }
+
+ /////////////////////////////
+ // Response/Event handlers
+
+-void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID)
++void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle)
+ {
+ if(statusCode != 0)
+ {
+@@ -3669,7 +2600,6 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
+ else
+ {
+ // Connector created, move forward.
+- LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
+ mConnectorHandle = connectorHandle;
+ if(getState() == stateConnectorStarting)
+ {
+@@ -3678,7 +2608,7 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
+ }
+ }
+
+-void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
++void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle)
+ {
+ LL_DEBUGS("Voice") << "Account.Login response (" << statusCode << "): " << statusString << LL_ENDL;
+
+@@ -3699,8 +2629,7 @@ void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std
+ {
+ // Login succeeded, move forward.
+ mAccountHandle = accountHandle;
+- mNumberOfAliases = numberOfAliases;
+- // This needs to wait until the AccountLoginStateChangeEvent is received.
++ // MBW -- XXX -- This needs to wait until the LoginStateChangeEvent is received.
+ // if(getState() == stateLoggingIn)
+ // {
+ // setState(stateLoggedIn);
+@@ -3708,91 +2637,106 @@ void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std
+ }
+ }
+
+-void LLVoiceClient::sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
+-{
+- sessionState *session = findSessionBeingCreatedByURI(requestId);
+-
+- if(session)
+- {
+- session->mCreateInProgress = false;
+- }
+-
++void LLVoiceClient::channelGetListResponse(int statusCode, std::string &statusString)
++{
+ if(statusCode != 0)
+ {
+- LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
+- if(session)
+- {
+- session->mErrorStatusCode = statusCode;
+- session->mErrorStatusString = statusString;
+- if(session == mAudioSession)
+- {
+- setState(stateJoinSessionFailed);
+- }
+- else
+- {
+- reapSession(session);
+- }
+- }
++ LL_WARNS("Voice") << "Account.ChannelGetList response failure: " << statusString << LL_ENDL;
++ switchChannel();
+ }
+ else
+ {
+- LL_INFOS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
+- if(session)
++ // Got the channel list, try to do a lookup.
++ std::string uri = findChannelURI(mChannelName);
++ if(uri.empty())
++ {
++ // Lookup failed, can't join a channel for this area.
++ LL_INFOS("Voice") << "failed to map channel name: " << mChannelName << LL_ENDL;
++ }
++ else
+ {
+- setSessionHandle(session, sessionHandle);
++ // We have a sip URL for this area.
++ LL_INFOS("Voice") << "mapped channel " << mChannelName << " to URI "<< uri << LL_ENDL;
+ }
++
++ // switchChannel with an empty uri string will do the right thing (leave channel and not rejoin)
++ switchChannel(uri);
+ }
+ }
+
+-void LLVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
++void LLVoiceClient::sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle)
+ {
+- sessionState *session = findSessionBeingCreatedByURI(requestId);
+-
+- if(session)
+- {
+- session->mCreateInProgress = false;
+- }
+-
+ if(statusCode != 0)
+ {
+- LL_WARNS("Voice") << "SessionGroup.AddSession response failure (" << statusCode << "): " << statusString << LL_ENDL;
+- if(session)
++ LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
++// if(statusCode == 1015)
++// {
++// if(getState() == stateJoiningSession)
++// {
++// // this happened during a real join. Going to sessionTerminated should cause a retry in appropriate cases.
++// LL_WARNS("Voice") << "session handle \"" << sessionHandle << "\", mSessionStateEventHandle \"" << mSessionStateEventHandle << "\""<< LL_ENDL;
++// if(!sessionHandle.empty())
++// {
++// // This session is bad. Terminate it.
++// mSessionHandle = sessionHandle;
++// sessionTerminateByHandle(sessionHandle);
++// setState(stateLeavingSession);
++// }
++// else if(!mSessionStateEventHandle.empty())
++// {
++// mSessionHandle = mSessionStateEventHandle;
++// sessionTerminateByHandle(mSessionStateEventHandle);
++// setState(stateLeavingSession);
++// }
++// else
++// {
++// setState(stateSessionTerminated);
++// }
++// }
++// else
++// {
++// // We didn't think we were in the middle of a join. Don't change state.
++// LL_WARNS("Voice") << "Not in stateJoiningSession, ignoring" << LL_ENDL;
++// }
++// }
++// else
+ {
+- session->mErrorStatusCode = statusCode;
+- session->mErrorStatusString = statusString;
+- if(session == mAudioSession)
+- {
+- setState(stateJoinSessionFailed);
+- }
+- else
+- {
+- reapSession(session);
+- }
++ mVivoxErrorStatusCode = statusCode;
++ mVivoxErrorStatusString = statusString;
++ setState(stateJoinSessionFailed);
+ }
+ }
+ else
+ {
+- LL_DEBUGS("Voice") << "SessionGroup.AddSession response received (success), session handle is " << sessionHandle << LL_ENDL;
+- if(session)
++ LL_DEBUGS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
++ if(getState() == stateJoiningSession)
+ {
+- setSessionHandle(session, sessionHandle);
++ // This is also grabbed in the SessionStateChangeEvent handler, but it might be useful to have it early...
++ mSessionHandle = sessionHandle;
++ }
++ else
++ {
++ // We should never get a session.create response in any state except stateJoiningSession. Things are out of sync. Kill this session.
++ sessionTerminateByHandle(sessionHandle);
+ }
+ }
+ }
+
+-void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString)
++void LLVoiceClient::sessionConnectResponse(int statusCode, std::string &statusString)
+ {
+- sessionState *session = findSession(requestId);
+ if(statusCode != 0)
+ {
+ LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL;
+- if(session)
++// if(statusCode == 1015)
++// {
++// LL_WARNS("Voice") << "terminating existing session" << LL_ENDL;
++// sessionTerminate();
++// }
++// else
+ {
+- session->mMediaConnectInProgress = false;
+- session->mErrorStatusCode = statusCode;
+- session->mErrorStatusString = statusString;
+- if(session == mAudioSession)
+- setState(stateJoinSessionFailed);
++ mVivoxErrorStatusCode = statusCode;
++ mVivoxErrorStatusString = statusString;
++ setState(stateJoinSessionFailed);
+ }
+ }
+ else
+@@ -3801,12 +2745,27 @@ void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCod
+ }
+ }
+
++void LLVoiceClient::sessionTerminateResponse(int statusCode, std::string &statusString)
++{
++ if(statusCode != 0)
++ {
++ LL_WARNS("Voice") << "Session.Terminate response failure: (" << statusCode << "): " << statusString << LL_ENDL;
++ if(getState() == stateLeavingSession)
++ {
++ // This is probably "(404): Server reporting Failure. Not a member of this conference."
++ // Do this so we don't get stuck.
++ setState(stateSessionTerminated);
++ }
++ }
++
++}
++
+ void LLVoiceClient::logoutResponse(int statusCode, std::string &statusString)
+ {
+ if(statusCode != 0)
+ {
+ LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL;
+- // Should this ever fail? do we care if it does?
++ // MBW -- XXX -- Should this ever fail? do we care if it does?
+ }
+
+ if(getState() == stateLoggingOut)
+@@ -3820,7 +2779,7 @@ void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statu
+ if(statusCode != 0)
+ {
+ LL_WARNS("Voice") << "Connector.InitiateShutdown response failure: " << statusString << LL_ENDL;
+- // Should this ever fail? do we care if it does?
++ // MBW -- XXX -- Should this ever fail? do we care if it does?
+ }
+
+ mConnected = false;
+@@ -3831,277 +2790,109 @@ void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statu
+ }
+ }
+
+-void LLVoiceClient::sessionAddedEvent(
++void LLVoiceClient::sessionStateChangeEvent(
+ std::string &uriString,
+- std::string &alias,
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle,
++ int statusCode,
++ std::string &statusString,
++ std::string &sessionHandle,
++ int state,
+ bool isChannel,
+- bool incoming,
+- std::string &nameString,
+- std::string &applicationString)
++ std::string &nameString)
+ {
+- sessionState *session = NULL;
+-
+- LL_INFOS("Voice") << "session " << uriString << ", alias " << alias << ", name " << nameString << " handle " << sessionHandle << LL_ENDL;
+-
+- session = addSession(uriString, sessionHandle);
+- if(session)
++ switch(state)
+ {
+- session->mGroupHandle = sessionGroupHandle;
+- session->mIsChannel = isChannel;
+- session->mIncoming = incoming;
+- session->mAlias = alias;
+-
+- // Generate a caller UUID -- don't need to do this for channels
+- if(!session->mIsChannel)
+- {
+- if(IDFromName(session->mSIPURI, session->mCallerID))
++ case 4: // I see this when joining the session
++ LL_INFOS("Voice") << "joined session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << LL_ENDL;
++
++ // Session create succeeded, move forward.
++ mSessionStateEventHandle = sessionHandle;
++ mSessionStateEventURI = uriString;
++ if(sessionHandle == mSessionHandle)
+ {
+- // Normal URI(base64-encoded UUID)
++ // This is the session we're joining.
++ if(getState() == stateJoiningSession)
++ {
++ setState(stateSessionJoined);
++ //RN: the uriString being returned by vivox here is actually your account uri, not the channel
++ // you are attempting to join, so ignore it
++ //LL_DEBUGS("Voice") << "received URI " << uriString << "(previously " << mSessionURI << ")" << LL_ENDL;
++ //mSessionURI = uriString;
++ }
+ }
+- else if(!session->mAlias.empty() && IDFromName(session->mAlias, session->mCallerID))
++ else if(sessionHandle == mNextSessionHandle)
+ {
+- // Wrong URI, but an alias is available. Stash the incoming URI as an alternate
+- session->mAlternateSIPURI = session->mSIPURI;
+-
+- // and generate a proper URI from the ID.
+- setSessionURI(session, sipURIFromID(session->mCallerID));
++// LL_DEBUGS("Voice") << "received URI " << uriString << ", name " << nameString << " for next session (handle " << mNextSessionHandle << ")" << LL_ENDL;
+ }
+ 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->mSynthesizedCallerID = true;
+-
+- // Can't look up the name in this case -- we have to extract it from the URI.
+- std::string namePortion = nameFromsipURI(session->mSIPURI);
+- if(namePortion.empty())
+- {
+- // Didn't seem to be a SIP URI, just use the whole provided name.
+- namePortion = nameString;
+- }
+-
+- // Some incoming names may be separated with an underscore instead of a space. Fix this.
+- LLStringUtil::replaceChar(namePortion, '_', ' ');
+-
+- // Act like we just finished resolving the name (this stores it in all the right places)
+- avatarNameResolved(session->mCallerID, namePortion);
++ LL_WARNS("Voice") << "joining unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << LL_ENDL;
++ // MBW -- XXX -- Should we send a Session.Terminate here?
+ }
+-
+- LL_INFOS("Voice") << "caller ID: " << session->mCallerID << LL_ENDL;
+-
+- if(!session->mSynthesizedCallerID)
+- {
+- // If we got here, we don't have a proper name. Initiate a lookup.
+- lookupName(session->mCallerID);
+- }
+- }
+- }
+-}
+-
+-void LLVoiceClient::sessionGroupAddedEvent(std::string &sessionGroupHandle)
+-{
+- LL_DEBUGS("Voice") << "handle " << sessionGroupHandle << LL_ENDL;
+-
+-#if USE_SESSION_GROUPS
+- if(mMainSessionGroupHandle.empty())
+- {
+- // This is the first (i.e. "main") session group. Save its handle.
+- mMainSessionGroupHandle = sessionGroupHandle;
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Already had a session group handle " << mMainSessionGroupHandle << LL_ENDL;
+- }
+-#endif
+-}
+-
+-void LLVoiceClient::joinedAudioSession(sessionState *session)
+-{
+- if(mAudioSession != session)
+- {
+- sessionState *oldSession = mAudioSession;
+-
+- mAudioSession = session;
+- mAudioSessionChanged = true;
+-
+- // The old session may now need to be deleted.
+- reapSession(oldSession);
+- }
+-
+- // This is the session we're joining.
+- if(getState() == stateJoiningSession)
+- {
+- setState(stateSessionJoined);
+-
+- // SLIM SDK: we don't always receive a participant state change for ourselves when joining a channel now.
+- // Add the current user as a participant here.
+- participantState *participant = session->addParticipant(sipURIFromName(mAccountName));
+- if(participant)
+- {
+- participant->mIsSelf = true;
+- lookupName(participant->mAvatarID);
++
++ break;
++ case 5: // I see this when leaving the session
++ LL_INFOS("Voice") << "left session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << LL_ENDL;
+
+- LL_INFOS("Voice") << "added self as participant \"" << participant->mAccountName
+- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
+- }
+-
+- if(!session->mIsChannel)
+- {
+- // this is a p2p session. Make sure the other end is added as a participant.
+- participantState *participant = session->addParticipant(session->mSIPURI);
+- if(participant)
++ // Set the session handle to the empty string. If we get back to stateJoiningSession, we'll want to wait for the new session handle.
++ if(sessionHandle == mSessionHandle)
+ {
+- if(participant->mAvatarIDValid)
++ // MBW -- XXX -- I think this is no longer necessary, now that we've got mNextSessionURI/mNextSessionHandle
++ // mSessionURI.clear();
++ // clear the session handle here just for sanity.
++ mSessionHandle.clear();
++ if(mSessionResetOnClose)
+ {
+- lookupName(participant->mAvatarID);
+- }
+- else if(!session->mName.empty())
+- {
+- participant->mDisplayName = session->mName;
+- avatarNameResolved(participant->mAvatarID, session->mName);
++ mSessionResetOnClose = false;
++ mNonSpatialChannel = false;
++ mNextSessionSpatial = true;
++ parcelChanged();
+ }
+-
+- // TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here?
+- LL_INFOS("Voice") << "added caller as participant \"" << participant->mAccountName
+- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
+- }
+- }
+- }
+-}
+-
+-void LLVoiceClient::sessionRemovedEvent(
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle)
+-{
+- LL_INFOS("Voice") << "handle " << sessionHandle << LL_ENDL;
+-
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- leftAudioSession(session);
+-
+- // This message invalidates the session's handle. Set it to empty.
+- setSessionHandle(session);
+-
+- // Reset the media state (we now have no info)
+- session->mMediaStreamState = streamStateUnknown;
+- session->mTextStreamState = streamStateUnknown;
+-
+- // Conditionally delete the session
+- reapSession(session);
+- }
+- else
+- {
+- LL_WARNS("Voice") << "unknown session " << sessionHandle << " removed" << LL_ENDL;
+- }
+-}
+-
+-void LLVoiceClient::reapSession(sessionState *session)
+-{
+- if(session)
+- {
+- if(!session->mHandle.empty())
+- {
+- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL;
+- }
+- else if(session->mCreateInProgress)
+- {
+- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL;
+- }
+- else if(session->mMediaConnectInProgress)
+- {
+- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL;
+- }
+- else if(session == mAudioSession)
+- {
+- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL;
+- }
+- else if(session == mNextAudioSession)
+- {
+- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL;
+- }
+- else
+- {
+- // TODO: Question: Should we check for queued text messages here?
+- // We don't have a reason to keep tracking this session, so just delete it.
+- LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL;
+- deleteSession(session);
+- session = NULL;
+- }
+- }
+- else
+- {
+-// LL_DEBUGS("Voice") << "session is NULL" << LL_ENDL;
+- }
+-}
+-
+-// Returns true if the session seems to indicate we've moved to a region on a different voice server
+-bool LLVoiceClient::sessionNeedsRelog(sessionState *session)
+-{
+- bool result = false;
+-
+- if(session != NULL)
+- {
+- // Only make this check for spatial channels (so it won't happen for group or p2p calls)
+- if(session->mIsSpatial)
+- {
+- std::string::size_type atsign;
+
+- atsign = session->mSIPURI.find("@");
+-
+- if(atsign != std::string::npos)
+- {
+- std::string urihost = session->mSIPURI.substr(atsign + 1);
+- if(stricmp(urihost.c_str(), mVoiceSIPURIHostName.c_str()))
++ removeAllParticipants();
++
++ switch(getState())
+ {
+- // The hostname in this URI is different from what we expect. This probably means we need to relog.
++ case stateJoiningSession:
++ case stateSessionJoined:
++ case stateRunning:
++ case stateLeavingSession:
++ case stateJoinSessionFailed:
++ case stateJoinSessionFailedWaiting:
++ // normal transition
++ LL_INFOS("Voice") << "left session " << sessionHandle << "in state " << state2string(getState()) << LL_ENDL;
++ setState(stateSessionTerminated);
++ break;
+
+- // We could make a ProvisionVoiceAccountRequest and compare the result with the current values of
+- // mVoiceSIPURIHostName and mVoiceAccountServerURI to be really sure, but this is a pretty good indicator.
++ case stateSessionTerminated:
++ // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
++ LL_WARNS("Voice") << "left session " << sessionHandle << "in state " << state2string(getState()) << LL_ENDL;
++ break;
+
+- result = true;
++ default:
++ LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
++ setState(stateSessionTerminated);
++ break;
+ }
++
++ // store status values for later notification of observers
++ mVivoxErrorStatusCode = statusCode;
++ mVivoxErrorStatusString = statusString;
++ }
++ else
++ {
++ LL_INFOS("Voice") << "leaving unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << LL_ENDL;
+ }
+- }
+- }
+-
+- return result;
+-}
+
+-void LLVoiceClient::leftAudioSession(
+- sessionState *session)
+-{
+- if(mAudioSession == session)
+- {
+- switch(getState())
+- {
+- case stateJoiningSession:
+- case stateSessionJoined:
+- case stateRunning:
+- case stateLeavingSession:
+- case stateJoinSessionFailed:
+- case stateJoinSessionFailedWaiting:
+- // normal transition
+- LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
+- setState(stateSessionTerminated);
+- break;
+-
+- case stateSessionTerminated:
+- // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
+- LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
+- break;
+-
+- default:
+- LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
+- setState(stateSessionTerminated);
+- break;
+- }
++ mSessionStateEventHandle.clear();
++ mSessionStateEventURI.clear();
++ break;
++ default:
++ LL_WARNS("Voice") << "unknown state: " << state << LL_ENDL;
++ break;
+ }
+ }
+
+-void LLVoiceClient::accountLoginStateChangeEvent(
++void LLVoiceClient::loginStateChangeEvent(
+ std::string &accountHandle,
+ int statusCode,
+ std::string &statusString,
+@@ -4134,571 +2925,110 @@ void LLVoiceClient::accountLoginStateChangeEvent(
+ }
+ }
+
+-void LLVoiceClient::mediaStreamUpdatedEvent(
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle,
+- int statusCode,
+- std::string &statusString,
+- int state,
+- bool incoming)
++void LLVoiceClient::sessionNewEvent(
++ std::string &accountHandle,
++ std::string &eventSessionHandle,
++ int state,
++ std::string &nameString,
++ std::string &uriString)
+ {
+- sessionState *session = findSession(sessionHandle);
+-
+- LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL;
++ LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
+
+- if(session)
+- {
+- // We know about this session
+-
+- // Save the state for later use
+- session->mMediaStreamState = state;
+-
+- switch(statusCode)
+- {
+- case 0:
+- case 200:
+- // generic success
+- // Don't change the saved error code (it may have been set elsewhere)
+- break;
+- default:
+- // save the status code for later
+- session->mErrorStatusCode = statusCode;
+- break;
+- }
+-
+- switch(state)
+- {
+- case streamStateIdle:
+- // Standard "left audio session"
+- session->mVoiceEnabled = false;
+- session->mMediaConnectInProgress = false;
+- leftAudioSession(session);
+- break;
+-
+- case streamStateConnected:
+- session->mVoiceEnabled = true;
+- session->mMediaConnectInProgress = false;
+- joinedAudioSession(session);
+- break;
+-
+- case streamStateRinging:
+- if(incoming)
+- {
+- // Send the voice chat invite to the GUI layer
+- // TODO: Question: Should we correlate with the mute list here?
+- session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
+- session->mVoiceInvitePending = true;
+- if(session->mName.empty())
+- {
+- lookupName(session->mCallerID);
+- }
+- else
+- {
+- // Act like we just finished resolving the name
+- avatarNameResolved(session->mCallerID, session->mName);
+- }
+- }
+- break;
+-
+- default:
+- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
+- break;
+-
+- }
+-
+- }
+- else
++ switch(state)
+ {
+- LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL;
+- }
+-}
++ case 0:
++ {
++ LL_DEBUGS("Voice") << "session handle = " << eventSessionHandle << ", name = " << nameString << ", uri = " << uriString << LL_ENDL;
+
+-void LLVoiceClient::textStreamUpdatedEvent(
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle,
+- bool enabled,
+- int state,
+- bool incoming)
+-{
+- sessionState *session = findSession(sessionHandle);
+-
+- if(session)
+- {
+- // Save the state for later use
+- session->mTextStreamState = state;
+-
+- // We know about this session
+- switch(state)
+- {
+- case 0: // We see this when the text stream closes
+- LL_DEBUGS("Voice") << "stream closed" << LL_ENDL;
+- break;
+-
+- case 1: // We see this on an incoming call from the Connector
+- // Try to send any text messages queued for this session.
+- sendQueuedTextMessages(session);
+-
+- // Send the text chat invite to the GUI layer
+- // TODO: Question: Should we correlate with the mute list here?
+- session->mTextInvitePending = true;
+- if(session->mName.empty())
++ LLUUID caller_id;
++ if(IDFromName(nameString, caller_id))
+ {
+- lookupName(session->mCallerID);
++ gIMMgr->inviteToSession(
++ LLIMMgr::computeSessionID(
++ IM_SESSION_P2P_INVITE,
++ caller_id),
++ LLStringUtil::null,
++ caller_id,
++ LLStringUtil::null,
++ IM_SESSION_P2P_INVITE,
++ LLIMMgr::INVITATION_TYPE_VOICE,
++ eventSessionHandle);
+ }
+ else
+ {
+- // Act like we just finished resolving the name
+- avatarNameResolved(session->mCallerID, session->mName);
++ LL_WARNS("Voice") << "Could not generate caller id from uri " << uriString << LL_ENDL;
+ }
+- break;
+-
+- default:
+- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
+- break;
+-
+- }
++ }
++ break;
++
++ default:
++ LL_WARNS("Voice") << "unknown state: " << state << LL_ENDL;
++ break;
+ }
+ }
+
+-void LLVoiceClient::participantAddedEvent(
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle,
++void LLVoiceClient::participantStateChangeEvent(
+ std::string &uriString,
+- std::string &alias,
++ int statusCode,
++ std::string &statusString,
++ int state,
+ std::string &nameString,
+ std::string &displayNameString,
+ int participantType)
+ {
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- participantState *participant = session->addParticipant(uriString);
+- if(participant)
+- {
+- participant->mAccountName = nameString;
+-
+- LL_DEBUGS("Voice") << "added participant \"" << participant->mAccountName
+- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
++ participantState *participant = NULL;
++ LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
+
+- if(participant->mAvatarIDValid)
++ switch(state)
++ {
++ case 7: // I see this when a participant joins
++ participant = addParticipant(uriString);
++ if(participant)
+ {
+- // Initiate a lookup
+- lookupName(participant->mAvatarID);
++ participant->mName = nameString;
++ LL_DEBUGS("Voice") << "added participant \"" << participant->mName
++ << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
+ }
+- else
++ break;
++ case 9: // I see this when a participant leaves
++ participant = findParticipant(uriString);
++ if(participant)
+ {
+- // If we don't have a valid avatar UUID, we need to fill in the display name to make the active speakers floater work.
+- std::string namePortion = nameFromsipURI(uriString);
+- if(namePortion.empty())
+- {
+- // Problem with the SIP URI, fall back to the display name
+- namePortion = displayNameString;
+- }
+- if(namePortion.empty())
+- {
+- // Problems with both of the above, fall back to the account name
+- namePortion = nameString;
+- }
+-
+- // Set the display name (which is a hint to the active speakers window not to do its own lookup)
+- participant->mDisplayName = namePortion;
+- avatarNameResolved(participant->mAvatarID, namePortion);
++ removeParticipant(participant);
+ }
+- }
+- }
+-}
+-
+-void LLVoiceClient::participantRemovedEvent(
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle,
+- std::string &uriString,
+- std::string &alias,
+- std::string &nameString)
+-{
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- participantState *participant = session->findParticipant(uriString);
+- if(participant)
+- {
+- session->removeParticipant(participant);
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "unknown participant " << uriString << LL_ENDL;
+- }
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
++ break;
++ default:
++ LL_DEBUGS("Voice") << "unknown state: " << state << LL_ENDL;
++ break;
+ }
+ }
+
+-
+-void LLVoiceClient::participantUpdatedEvent(
+- std::string &sessionHandle,
+- std::string &sessionGroupHandle,
++void LLVoiceClient::participantPropertiesEvent(
+ std::string &uriString,
+- std::string &alias,
++ int statusCode,
++ std::string &statusString,
++ bool isLocallyMuted,
+ bool isModeratorMuted,
+ bool isSpeaking,
+ int volume,
+ F32 energy)
+ {
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- participantState *participant = session->findParticipant(uriString);
+-
+- if(participant)
+- {
+- participant->mIsSpeaking = isSpeaking;
+- participant->mIsModeratorMuted = isModeratorMuted;
+-
+- // SLIM SDK: convert range: ensure that energy is set to zero if is_speaking is false
+- if (isSpeaking)
+- {
+- participant->mSpeakingTimeout.reset();
+- participant->mPower = energy;
+- }
+- else
+- {
+- participant->mPower = 0.0f;
+- }
+- participant->mVolume = volume;
+- }
+- else
+- {
+- LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
+- }
+- }
+- else
+- {
+- LL_INFOS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
+- }
+-}
+-
+-void LLVoiceClient::buddyPresenceEvent(
+- std::string &uriString,
+- std::string &alias,
+- std::string &statusString,
+- std::string &applicationString)
+-{
+- buddyListEntry *buddy = findBuddy(uriString);
+-
+- if(buddy)
++ participantState *participant = findParticipant(uriString);
++ if(participant)
+ {
+- LL_DEBUGS("Voice") << "Presence event for " << buddy->mDisplayName << " status \"" << statusString << "\", application \"" << applicationString << "\""<< LL_ENDL;
+- LL_DEBUGS("Voice") << "before: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
+-
+- if(applicationString.empty())
++ participant->mPTT = !isLocallyMuted;
++ participant->mIsSpeaking = isSpeaking;
++ participant->mIsModeratorMuted = isModeratorMuted;
++ if (isSpeaking)
+ {
+- // This presence event is from a client that doesn't set up the Application string. Do things the old-skool way.
+- // NOTE: this will be needed to support people who aren't on the 3010-class SDK yet.
+-
+- if ( stricmp("Unknown", statusString.c_str())== 0)
+- {
+- // User went offline with a non-SLim-enabled viewer.
+- buddy->mOnlineSL = false;
+- }
+- else if ( stricmp("Online", statusString.c_str())== 0)
+- {
+- // User came online with a non-SLim-enabled viewer.
+- buddy->mOnlineSL = true;
+- }
+- else
+- {
+- // If the user is online through SLim, their status will be "Online-slc", "Away", or something else.
+- // NOTE: we should never see this unless someone is running an OLD version of SLim -- the versions that should be in use now all set the application string.
+- buddy->mOnlineSLim = true;
+- }
++ participant->mSpeakingTimeout.reset();
+ }
+- else if(applicationString.find("SecondLifeViewer") != std::string::npos)
+- {
+- // This presence event is from a viewer that sets the application string
+- if ( stricmp("Unknown", statusString.c_str())== 0)
+- {
+- // Viewer says they're offline
+- buddy->mOnlineSL = false;
+- }
+- else
+- {
+- // Viewer says they're online
+- buddy->mOnlineSL = true;
+- }
+- }
+- else
+- {
+- // This presence event is from something which is NOT the SL viewer (assume it's SLim).
+- if ( stricmp("Unknown", statusString.c_str())== 0)
+- {
+- // SLim says they're offline
+- buddy->mOnlineSLim = false;
+- }
+- else
+- {
+- // SLim says they're online
+- buddy->mOnlineSLim = true;
+- }
+- }
+-
+- LL_DEBUGS("Voice") << "after: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
+-
+- // HACK -- increment the internal change serial number in the LLRelationship (without changing the actual status), so the UI notices the change.
+- LLAvatarTracker::instance().setBuddyOnline(buddy->mUUID,LLAvatarTracker::instance().isBuddyOnline(buddy->mUUID));
+-
+- notifyFriendObservers();
++ participant->mPower = energy;
++ participant->mVolume = volume;
+ }
+ else
+ {
+- LL_DEBUGS("Voice") << "Presence for unknown buddy " << uriString << LL_ENDL;
+- }
+-}
+-
+-void LLVoiceClient::messageEvent(
+- std::string &sessionHandle,
+- std::string &uriString,
+- std::string &alias,
+- std::string &messageHeader,
+- std::string &messageBody,
+- std::string &applicationString)
+-{
+- LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL;
+-// LL_DEBUGS("Voice") << " header " << messageHeader << ", body: \n" << messageBody << LL_ENDL;
+-
+- if(messageHeader.find("text/html") != std::string::npos)
+- {
+- std::string rawMessage;
+-
+- {
+- const std::string startMarker = ", try looking for a instead.
+- start = messageBody.find(startSpan);
+- start = messageBody.find(startMarker2, start);
+- end = messageBody.find(endSpan);
+-
+- if(start != std::string::npos)
+- {
+- start += startMarker2.size();
+-
+- if(end != std::string::npos)
+- end -= start;
+-
+- rawMessage.assign(messageBody, start, end);
+- }
+- }
+- }
+-
+-// LL_DEBUGS("Voice") << " raw message = \n" << rawMessage << LL_ENDL;
+-
+- // strip formatting tags
+- {
+- std::string::size_type start;
+- std::string::size_type end;
+-
+- while((start = rawMessage.find('<')) != std::string::npos)
+- {
+- if((end = rawMessage.find('>', start + 1)) != std::string::npos)
+- {
+- // Strip out the tag
+- rawMessage.erase(start, (end + 1) - start);
+- }
+- else
+- {
+- // Avoid an infinite loop
+- break;
+- }
+- }
+- }
+-
+- // Decode ampersand-escaped chars
+- {
+- std::string::size_type mark = 0;
+-
+- // The text may contain text encoded with <, >, and &
+- mark = 0;
+- while((mark = rawMessage.find("<", mark)) != std::string::npos)
+- {
+- rawMessage.replace(mark, 4, "<");
+- mark += 1;
+- }
+-
+- mark = 0;
+- while((mark = rawMessage.find(">", mark)) != std::string::npos)
+- {
+- rawMessage.replace(mark, 4, ">");
+- mark += 1;
+- }
+-
+- mark = 0;
+- while((mark = rawMessage.find("&", mark)) != std::string::npos)
+- {
+- rawMessage.replace(mark, 5, "&");
+- mark += 1;
+- }
+- }
+-
+- // strip leading/trailing whitespace (since we always seem to get a couple newlines)
+- LLStringUtil::trim(rawMessage);
+-
+-// LL_DEBUGS("Voice") << " stripped message = \n" << rawMessage << LL_ENDL;
+-
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- bool is_busy = gAgent.getBusy();
+- bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
+- bool is_linden = LLMuteList::getInstance()->isLinden(session->mName);
+- bool quiet_chat = false;
+- LLChat chat;
+-
+- chat.mMuted = is_muted && !is_linden;
+-
+- if(!chat.mMuted)
+- {
+- chat.mFromID = session->mCallerID;
+- chat.mFromName = session->mName;
+- chat.mSourceType = CHAT_SOURCE_AGENT;
+-
+- if(is_busy && !is_linden)
+- {
+- quiet_chat = true;
+- // TODO: Question: Return busy mode response here? Or maybe when session is started instead?
+- }
+-
+- std::string fullMessage = std::string(": ") + rawMessage;
+-
+- LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
+- gIMMgr->addMessage(session->mIMSessionID,
+- session->mCallerID,
+- session->mName.c_str(),
+- fullMessage.c_str(),
+- LLStringUtil::null, // default arg
+- IM_NOTHING_SPECIAL, // default arg
+- 0, // default arg
+- LLUUID::null, // default arg
+- LLVector3::zero, // default arg
+- true); // prepend name and make it a link to the user's profile
+-
+- chat.mText = std::string("IM: ") + session->mName + std::string(": ") + rawMessage;
+- // If the chat should come in quietly (i.e. we're in busy mode), pretend it's from a local agent.
+- LLFloaterChat::addChat( chat, TRUE, quiet_chat );
+- }
+- }
+- }
+-}
+-
+-void LLVoiceClient::sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string ¬ificationType)
+-{
+- sessionState *session = findSession(sessionHandle);
+-
+- if(session)
+- {
+- participantState *participant = session->findParticipant(uriString);
+- if(participant)
+- {
+- if (!stricmp(notificationType.c_str(), "Typing"))
+- {
+- // Other end started typing
+- // TODO: The proper way to add a typing notification seems to be LLIMMgr::processIMTypingStart().
+- // It requires an LLIMInfo for the message, which we don't have here.
+- }
+- else if (!stricmp(notificationType.c_str(), "NotTyping"))
+- {
+- // Other end stopped typing
+- // TODO: The proper way to remove a typing notification seems to be LLIMMgr::processIMTypingStop().
+- // It requires an LLIMInfo for the message, which we don't have here.
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Unknown notification type " << notificationType << "for participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
+- }
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Unknown participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
+- }
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Unknown session handle " << sessionHandle << LL_ENDL;
+- }
+-}
+-
+-void LLVoiceClient::subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType)
+-{
+- buddyListEntry *buddy = findBuddy(buddyURI);
+-
+- if(!buddy)
+- {
+- // Couldn't find buddy by URI, try converting the alias...
+- if(!alias.empty())
+- {
+- LLUUID id;
+- if(IDFromName(alias, id))
+- {
+- buddy = findBuddy(id);
+- }
+- }
+- }
+-
+- if(buddy)
+- {
+- std::ostringstream stream;
+-
+- if(buddy->mCanSeeMeOnline)
+- {
+- // Sending the response will create an auto-accept rule
+- buddy->mHasAutoAcceptListEntry = true;
+- }
+- else
+- {
+- // Sending the response will create a block rule
+- buddy->mHasBlockListEntry = true;
+- }
+-
+- if(buddy->mInSLFriends)
+- {
+- buddy->mInVivoxBuddies = true;
+- }
+-
+- stream
+- << ""
+- << "" << mAccountHandle << ""
+- << "" << buddy->mURI << ""
+- << "" << (buddy->mCanSeeMeOnline?"Allow":"Hide") << ""
+- << ""<< (buddy->mInSLFriends?"1":"0")<< ""
+- << "" << subscriptionHandle << ""
+- << ""
+- << "\n\n\n";
+-
+- writeString(stream.str());
++ LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
+ }
+ }
+
+@@ -4708,226 +3038,155 @@ void LLVoiceClient::auxAudioPropertiesEvent(F32 energy)
+ mTuningEnergy = energy;
+ }
+
+-void LLVoiceClient::buddyListChanged()
+-{
+- // This is called after we receive a BuddyAndGroupListChangedEvent.
+- mBuddyListMapPopulated = true;
+- mFriendsListDirty = true;
+-}
+-
+ void LLVoiceClient::muteListChanged()
+ {
+ // The user's mute list has been updated. Go through the current participant list and sync it with the mute list.
+- if(mAudioSession)
+- {
+- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
+-
+- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
+- {
+- participantState *p = iter->second;
+-
+- // Check to see if this participant is on the mute list already
+- if(p->updateMuteState())
+- mAudioSession->mVolumeDirty = true;
+- }
+- }
+-}
+
+-void LLVoiceClient::updateFriends(U32 mask)
+-{
+- if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::POWERS))
++ participantMap::iterator iter = mParticipantMap.begin();
++
++ for(; iter != mParticipantMap.end(); iter++)
+ {
+- // Just resend the whole friend list to the daemon
+- mFriendsListDirty = true;
++ participantState *p = iter->second;
++
++ // Check to see if this participant is on the mute list already
++ updateMuteState(p);
+ }
+ }
+
+ /////////////////////////////
+ // Managing list of participants
+ LLVoiceClient::participantState::participantState(const std::string &uri) :
+- mURI(uri),
+- mPTT(false),
+- mIsSpeaking(false),
+- mIsModeratorMuted(false),
+- mLastSpokeTimestamp(0.f),
+- mPower(0.f),
+- mVolume(0),
+- mOnMuteList(false),
+- mUserVolume(100),
+- mVolumeDirty(false),
+- mAvatarIDValid(false),
+- mIsSelf(false)
++ mURI(uri), mPTT(false), mIsSpeaking(false), mIsModeratorMuted(false), mLastSpokeTimestamp(0.f), mPower(0.f), mVolume(0), mServiceType(serviceTypeUnknown),
++ mOnMuteList(false), mUserVolume(100), mVolumeDirty(false), mAvatarIDValid(false)
+ {
+ }
+
+-LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(const std::string &uri)
++LLVoiceClient::participantState *LLVoiceClient::addParticipant(const std::string &uri)
+ {
+ participantState *result = NULL;
+- bool useAlternateURI = false;
++
++ participantMap::iterator iter = mParticipantMap.find(uri);
+
+- // Note: this is mostly the body of LLVoiceClient::sessionState::findParticipant(), but since we need to know if it
+- // matched the alternate SIP URI (so we can add it properly), we need to reproduce it here.
++ if(iter != mParticipantMap.end())
+ {
+- participantMap::iterator iter = mParticipantsByURI.find(&uri);
+-
+- if(iter == mParticipantsByURI.end())
+- {
+- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
+- {
+- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
+- // Use mSIPURI instead, since it will be properly encoded.
+- iter = mParticipantsByURI.find(&(mSIPURI));
+- useAlternateURI = true;
+- }
+- }
+-
+- if(iter != mParticipantsByURI.end())
+- {
+- result = iter->second;
+- }
++ // Found a matching participant already in the map.
++ result = iter->second;
+ }
+-
++
+ if(!result)
+ {
+ // participant isn't already in one list or the other.
+- result = new participantState(useAlternateURI?mSIPURI:uri);
+- mParticipantsByURI.insert(participantMap::value_type(&(result->mURI), result));
+- mParticipantsChanged = true;
++ result = new participantState(uri);
++ mParticipantMap.insert(participantMap::value_type(uri, result));
++ mParticipantMapChanged = true;
+
+ // Try to do a reverse transform on the URI to get the GUID back.
+ {
+ LLUUID id;
+- if(IDFromName(result->mURI, id))
++ if(IDFromName(uri, id))
+ {
+ result->mAvatarIDValid = true;
+ result->mAvatarID = id;
+
+- if(result->updateMuteState())
+- mVolumeDirty = true;
+- }
+- else
+- {
+- // 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);
++ updateMuteState(result);
+ }
+ }
+
+- mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result));
+-
+ LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
+ }
+
+ return result;
+ }
+
+-bool LLVoiceClient::participantState::updateMuteState()
++void LLVoiceClient::updateMuteState(participantState *p)
+ {
+- bool result = false;
+-
+- if(mAvatarIDValid)
++ if(p->mAvatarIDValid)
+ {
+- bool isMuted = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
+- if(mOnMuteList != isMuted)
++ bool isMuted = LLMuteList::getInstance()->isMuted(p->mAvatarID, LLMute::flagVoiceChat);
++ if(p->mOnMuteList != isMuted)
+ {
+- mOnMuteList = isMuted;
++ p->mOnMuteList = isMuted;
++ p->mVolumeDirty = true;
+ mVolumeDirty = true;
+- result = true;
+ }
+ }
+- return result;
+ }
+
+-void LLVoiceClient::sessionState::removeParticipant(LLVoiceClient::participantState *participant)
++void LLVoiceClient::removeParticipant(LLVoiceClient::participantState *participant)
+ {
+ if(participant)
+ {
+- participantMap::iterator iter = mParticipantsByURI.find(&(participant->mURI));
+- participantUUIDMap::iterator iter2 = mParticipantsByUUID.find(&(participant->mAvatarID));
+-
++ participantMap::iterator iter = mParticipantMap.find(participant->mURI);
++
+ LL_DEBUGS("Voice") << "participant \"" << participant->mURI << "\" (" << participant->mAvatarID << ") removed." << LL_ENDL;
+-
+- if(iter == mParticipantsByURI.end())
+- {
+- LL_ERRS("Voice") << "Internal error: participant " << participant->mURI << " not in URI map" << LL_ENDL;
+- }
+- else if(iter2 == mParticipantsByUUID.end())
+- {
+- LL_ERRS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL;
+- }
+- else if(iter->second != iter2->second)
+- {
+- LL_ERRS("Voice") << "Internal error: participant mismatch!" << LL_ENDL;
+- }
+- else
+- {
+- mParticipantsByURI.erase(iter);
+- mParticipantsByUUID.erase(iter2);
+-
+- delete participant;
+- mParticipantsChanged = true;
+- }
++
++ mParticipantMap.erase(iter);
++ delete participant;
++ mParticipantMapChanged = true;
+ }
+ }
+
+-void LLVoiceClient::sessionState::removeAllParticipants()
++void LLVoiceClient::removeAllParticipants()
+ {
+ LL_DEBUGS("Voice") << "called" << LL_ENDL;
+
+- while(!mParticipantsByURI.empty())
++ while(!mParticipantMap.empty())
+ {
+- removeParticipant(mParticipantsByURI.begin()->second);
+- }
+-
+- if(!mParticipantsByUUID.empty())
+- {
+- LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL
++ removeParticipant(mParticipantMap.begin()->second);
+ }
+ }
+
+ LLVoiceClient::participantMap *LLVoiceClient::getParticipantList(void)
+ {
+- participantMap *result = NULL;
+- if(mAudioSession)
+- {
+- result = &(mAudioSession->mParticipantsByURI);
+- }
+- return result;
++ return &mParticipantMap;
+ }
+
+
+-LLVoiceClient::participantState *LLVoiceClient::sessionState::findParticipant(const std::string &uri)
++LLVoiceClient::participantState *LLVoiceClient::findParticipant(const std::string &uri)
+ {
+ participantState *result = NULL;
+
+- participantMap::iterator iter = mParticipantsByURI.find(&uri);
+-
+- if(iter == mParticipantsByURI.end())
++ // Don't find any participants if we're not connected. This is so that we don't continue to get stale data
++ // after the daemon dies.
++ if(mConnected)
+ {
+- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
++ participantMap::iterator iter = mParticipantMap.find(uri);
++
++ if(iter != mParticipantMap.end())
+ {
+- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
+- // Look up the other URI
+- iter = mParticipantsByURI.find(&(mSIPURI));
++ result = iter->second;
+ }
+ }
+-
+- if(iter != mParticipantsByURI.end())
+- {
+- result = iter->second;
+- }
+-
++
+ return result;
+ }
+
+-LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByID(const LLUUID& id)
++
++LLVoiceClient::participantState *LLVoiceClient::findParticipantByAvatar(LLVOAvatar *avatar)
+ {
+ participantState * result = NULL;
+- participantUUIDMap::iterator iter = mParticipantsByUUID.find(&id);
+
+- if(iter != mParticipantsByUUID.end())
++ // You'd think this would work, but it doesn't...
++// std::string uri = sipURIFromAvatar(avatar);
++
++ // Currently, the URI is just the account name.
++ std::string loginName = nameFromAvatar(avatar);
++ result = findParticipant(loginName);
++
++ if(result != NULL)
+ {
+- result = iter->second;
++ if(!result->mAvatarIDValid)
++ {
++ result->mAvatarID = avatar->getID();
++ result->mAvatarIDValid = true;
++
++ // We just figured out the avatar ID, so the participant list has "changed" from the perspective of anyone who uses that to identify participants.
++ mParticipantMapChanged = true;
++
++ updateMuteState(result);
++ }
++
++
+ }
+
+ return result;
+@@ -4936,19 +3195,43 @@ LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByI
+ LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID& id)
+ {
+ participantState * result = NULL;
++
++ // Currently, the URI is just the account name.
++ std::string loginName = nameFromID(id);
++ result = findParticipant(loginName);
++
++ return result;
++}
++
++
++void LLVoiceClient::clearChannelMap(void)
++{
++ mChannelMap.clear();
++}
++
++void LLVoiceClient::addChannelMapEntry(std::string &name, std::string &uri)
++{
++ LL_DEBUGS("Voice") << "Adding channel name mapping: " << name << " -> " << uri << LL_ENDL;
++ mChannelMap.insert(channelMap::value_type(name, uri));
++}
++
++std::string LLVoiceClient::findChannelURI(std::string &name)
++{
++ std::string result;
+
+- if(mAudioSession)
++ channelMap::iterator iter = mChannelMap.find(name);
++
++ if(iter != mChannelMap.end())
+ {
+- result = mAudioSession->findParticipantByID(id);
++ result = iter->second;
+ }
+
+ return result;
+ }
+
+-
+ void LLVoiceClient::parcelChanged()
+ {
+- if(getState() >= stateNoChannel)
++ if(getState() >= stateLoggedIn)
+ {
+ // If the user is logged in, start a channel lookup.
+ LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
+@@ -4962,7 +3245,7 @@ void LLVoiceClient::parcelChanged()
+ }
+ else
+ {
+- // The transition to stateNoChannel needs to kick this off again.
++ // The transition to stateLoggedIn needs to kick this off again.
+ LL_INFOS("Voice") << "not logged in yet, deferring" << LL_ENDL;
+ }
+ }
+@@ -4970,17 +3253,12 @@ void LLVoiceClient::parcelChanged()
+ void LLVoiceClient::switchChannel(
+ std::string uri,
+ bool spatial,
+- bool no_reconnect,
+- bool is_p2p,
++ bool noReconnect,
+ std::string hash)
+ {
+ bool needsSwitch = false;
+
+- LL_DEBUGS("Voice")
+- << "called in state " << state2string(getState())
+- << " with uri \"" << uri << "\""
+- << (spatial?", spatial is true":", spatial is false")
+- << LL_ENDL;
++ LL_DEBUGS("Voice") << "called in state " << state2string(getState()) << " with uri \"" << uri << "\"" << LL_ENDL;
+
+ switch(getState())
+ {
+@@ -4990,18 +3268,18 @@ void LLVoiceClient::switchChannel(
+ // Always switch to the new URI from these states.
+ needsSwitch = true;
+ break;
+-
++
+ default:
+ if(mSessionTerminateRequested)
+ {
+ // If a terminate has been requested, we need to compare against where the URI we're already headed to.
+- if(mNextAudioSession && (mNextAudioSession->mSIPURI != uri))
++ if(mNextSessionURI != uri)
+ needsSwitch = true;
+ }
+ else
+ {
+ // Otherwise, compare against the URI we're in now.
+- if(mAudioSession && (mAudioSession->mSIPURI != uri))
++ if(mSessionURI != uri)
+ needsSwitch = true;
+ }
+ break;
+@@ -5009,28 +3287,22 @@ void LLVoiceClient::switchChannel(
+
+ if(needsSwitch)
+ {
++ mNextSessionURI = uri;
++ mNextSessionHash = hash;
++ mNextSessionHandle.clear();
++ mNextP2PSessionURI.clear();
++ mNextSessionSpatial = spatial;
++ mNextSessionNoReconnect = noReconnect;
++
+ if(uri.empty())
+ {
+ // Leave any channel we may be in
+ LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL;
+-
+- sessionState *oldSession = mNextAudioSession;
+- mNextAudioSession = NULL;
+-
+- // The old session may now need to be deleted.
+- reapSession(oldSession);
+-
+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
+ }
+ else
+ {
+ LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL;
+-
+- mNextAudioSession = addSession(uri);
+- mNextAudioSession->mHash = hash;
+- mNextAudioSession->mIsSpatial = spatial;
+- mNextAudioSession->mReconnect = !no_reconnect;
+- mNextAudioSession->mIsP2P = is_p2p;
+ }
+
+ if(getState() <= stateNoChannel)
+@@ -5045,10 +3317,15 @@ void LLVoiceClient::switchChannel(
+ }
+ }
+
+-void LLVoiceClient::joinSession(sessionState *session)
++void LLVoiceClient::joinSession(std::string handle, std::string uri)
+ {
+- mNextAudioSession = session;
+-
++ mNextSessionURI.clear();
++ mNextSessionHash.clear();
++ mNextP2PSessionURI = uri;
++ mNextSessionHandle = handle;
++ mNextSessionSpatial = false;
++ mNextSessionNoReconnect = false;
++
+ if(getState() <= stateNoChannel)
+ {
+ // We're already set up to join a channel, just needed to fill in the session handle
+@@ -5064,7 +3341,7 @@ void LLVoiceClient::setNonSpatialChannel(
+ const std::string &uri,
+ const std::string &credentials)
+ {
+- switchChannel(uri, false, false, false, credentials);
++ switchChannel(uri, false, false, credentials);
+ }
+
+ void LLVoiceClient::setSpatialChannel(
+@@ -5072,216 +3349,51 @@ void LLVoiceClient::setSpatialChannel(
+ const std::string &credentials)
+ {
+ mSpatialSessionURI = uri;
+- mSpatialSessionCredentials = credentials;
+ mAreaVoiceDisabled = mSpatialSessionURI.empty();
+
+ LL_DEBUGS("Voice") << "got spatial channel uri: \"" << uri << "\"" << LL_ENDL;
+
+- if((mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial)))
++ if(mNonSpatialChannel || !mNextSessionSpatial)
+ {
+ // User is in a non-spatial chat or joining a non-spatial chat. Don't switch channels.
+ LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL;
+ }
+ else
+ {
+- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
++ switchChannel(mSpatialSessionURI, true, false, credentials);
+ }
+ }
+
+-void LLVoiceClient::callUser(const LLUUID &uuid)
++void LLVoiceClient::callUser(LLUUID &uuid)
+ {
+ std::string userURI = sipURIFromID(uuid);
+
+- switchChannel(userURI, false, true, true);
+-}
+-
+-LLVoiceClient::sessionState* LLVoiceClient::startUserIMSession(const LLUUID &uuid)
+-{
+- // Figure out if a session with the user already exists
+- sessionState *session = findSession(uuid);
+- if(!session)
+- {
+- // No session with user, need to start one.
+- std::string uri = sipURIFromID(uuid);
+- session = addSession(uri);
+- session->mIsSpatial = false;
+- session->mReconnect = false;
+- session->mIsP2P = true;
+- session->mCallerID = uuid;
+- }
+-
+- if(session)
+- {
+- if(session->mHandle.empty())
+- {
+- // Session isn't active -- start it up.
+- sessionCreateSendMessage(session, false, true);
+- }
+- else
+- {
+- // Session is already active -- start up text.
+- sessionTextConnectSendMessage(session);
+- }
+- }
+-
+- return session;
+-}
+-
+-bool LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message)
+-{
+- bool result = false;
+-
+- // Attempt to locate the indicated session
+- sessionState *session = startUserIMSession(participant_id);
+- if(session)
+- {
+- // found the session, attempt to send the message
+- session->mTextMsgQueue.push(message);
+-
+- // Try to send queued messages (will do nothing if the session is not open yet)
+- sendQueuedTextMessages(session);
+-
+- // The message is queued, so we succeed.
+- result = true;
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL;
+- }
+-
+- return result;
+-}
+-
+-void LLVoiceClient::sendQueuedTextMessages(sessionState *session)
+-{
+- if(session->mTextStreamState == 1)
+- {
+- if(!session->mTextMsgQueue.empty())
+- {
+- std::ostringstream stream;
+-
+- while(!session->mTextMsgQueue.empty())
+- {
+- std::string message = session->mTextMsgQueue.front();
+- session->mTextMsgQueue.pop();
+- stream
+- << ""
+- << "" << session->mHandle << ""
+- << "text/HTML"
+- << "" << message << ""
+- << ""
+- << "\n\n\n";
+- }
+- writeString(stream.str());
+- }
+- }
+- else
+- {
+- // Session isn't connected yet, defer until later.
+- }
+-}
+-
+-void LLVoiceClient::endUserIMSession(const LLUUID &uuid)
+-{
+- // Figure out if a session with the user exists
+- sessionState *session = findSession(uuid);
+- if(session)
+- {
+- // found the session
+- if(!session->mHandle.empty())
+- {
+- sessionTextDisconnectSendMessage(session);
+- }
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL;
+- }
++ switchChannel(userURI, false, true);
+ }
+
+-bool LLVoiceClient::answerInvite(std::string &sessionHandle)
++void LLVoiceClient::answerInvite(std::string &sessionHandle, LLUUID& other_user_id)
+ {
+- // this is only ever used to answer incoming p2p call invites.
+-
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- session->mIsSpatial = false;
+- session->mReconnect = false;
+- session->mIsP2P = true;
+-
+- joinSession(session);
+- return true;
+- }
+-
+- return false;
+-}
+-
+-bool LLVoiceClient::isOnlineSIP(const LLUUID &id)
+-{
+- bool result = false;
+- buddyListEntry *buddy = findBuddy(id);
+- if(buddy)
+- {
+- result = buddy->mOnlineSLim;
+- LL_DEBUGS("Voice") << "Buddy " << buddy->mDisplayName << " is SIP " << (result?"online":"offline") << LL_ENDL;
+- }
+-
+- if(!result)
+- {
+- // This user isn't on the buddy list or doesn't show online status through the buddy list, but could be a participant in an existing session if they initiated a text IM.
+- sessionState *session = findSession(id);
+- if(session && !session->mHandle.empty())
+- {
+- if((session->mTextStreamState != streamStateUnknown) || (session->mMediaStreamState > streamStateIdle))
+- {
+- LL_DEBUGS("Voice") << "Open session with " << id << " found, returning SIP online state" << LL_ENDL;
+- // we have a p2p text session open with this user, so by definition they're online.
+- result = true;
+- }
+- }
+- }
+-
+- return result;
++ joinSession(sessionHandle, sipURIFromID(other_user_id));
+ }
+
+ void LLVoiceClient::declineInvite(std::string &sessionHandle)
+ {
+- sessionState *session = findSession(sessionHandle);
+- if(session)
+- {
+- sessionMediaDisconnectSendMessage(session);
+- }
++ sessionTerminateByHandle(sessionHandle);
+ }
+
+ void LLVoiceClient::leaveNonSpatialChannel()
+ {
+- LL_DEBUGS("Voice")
+- << "called in state " << state2string(getState())
+- << LL_ENDL;
+-
+- // Make sure we don't rejoin the current session.
+- sessionState *oldNextSession = mNextAudioSession;
+- mNextAudioSession = NULL;
+-
+- // Most likely this will still be the current session at this point, but check it anyway.
+- reapSession(oldNextSession);
+-
+- verifySessionState();
+-
+- sessionTerminate();
++ switchChannel(mSpatialSessionURI);
+ }
+
+ std::string LLVoiceClient::getCurrentChannel()
+ {
+- std::string result;
+-
+ if((getState() == stateRunning) && !mSessionTerminateRequested)
+ {
+- result = getAudioSessionURI();
++ return mSessionURI;
+ }
+
+- return result;
++ return "";
+ }
+
+ bool LLVoiceClient::inProximalChannel()
+@@ -5290,7 +3402,7 @@ bool LLVoiceClient::inProximalChannel()
+
+ if((getState() == stateRunning) && !mSessionTerminateRequested)
+ {
+- result = inSpatialChannel();
++ result = !mNonSpatialChannel;
+ }
+
+ return result;
+@@ -5302,7 +3414,7 @@ std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
+ result = "sip:";
+ result += nameFromID(id);
+ result += "@";
+- result += mVoiceSIPURIHostName;
++ result += mAccountServerName;
+
+ return result;
+ }
+@@ -5315,7 +3427,7 @@ std::string LLVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar)
+ result = "sip:";
+ result += nameFromID(avatar->getID());
+ result += "@";
+- result += mVoiceSIPURIHostName;
++ result += mAccountServerName;
+ }
+
+ return result;
+@@ -5334,13 +3446,6 @@ std::string LLVoiceClient::nameFromAvatar(LLVOAvatar *avatar)
+ std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
+ {
+ std::string result;
+-
+- if (uuid.isNull()) {
+- //VIVOX, the uuid emtpy look for the mURIString and return that instead.
+- //result.assign(uuid.mURIStringName);
+- LLStringUtil::replaceChar(result, '_', ' ');
+- return result;
+- }
+ // Prepending this apparently prevents conflicts with reserved names inside the vivox and diamondware code.
+ result = "x";
+
+@@ -5354,24 +3459,13 @@ std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
+ // If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
+ // echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
+
+- // The reverse transform can be done with:
+- // echo 'x5mkTKmxDTuGnjWyC__WfMg==' |cut -b 2- -|tr '_-' '/+' |openssl base64 -d|xxd -p
+-
+ return result;
+ }
+
+-bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
++bool LLVoiceClient::IDFromName(const std::string name, LLUUID &uuid)
+ {
+ bool result = false;
+
+- // SLIM SDK: The "name" may actually be a SIP URI such as: "sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com"
+- // If it is, convert to a bare name before doing the transform.
+- std::string name = nameFromsipURI(inName);
+-
+- // Doesn't look like a SIP URI, assume it's an actual name.
+- if(name.empty())
+- name = inName;
+-
+ // This will only work if the name is of the proper form.
+ // As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is:
+ // "xFnPP04IpREWNkuw1cOXlhw=="
+@@ -5393,13 +3487,6 @@ bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
+ memcpy(uuid.mData, rawuuid, UUID_BYTES);
+ result = true;
+ }
+- }
+-
+- if(!result)
+- {
+- // VIVOX: not a standard account name, just copy the URI name mURIString field
+- // and hope for the best. bpj
+- uuid.setNull(); // VIVOX, set the uuid field to nulls
+ }
+
+ return result;
+@@ -5416,59 +3503,13 @@ std::string LLVoiceClient::sipURIFromName(std::string &name)
+ result = "sip:";
+ result += name;
+ result += "@";
+- result += mVoiceSIPURIHostName;
++ result += mAccountServerName;
+
+ // LLStringUtil::toLower(result);
+
+ return result;
+ }
+
+-std::string LLVoiceClient::nameFromsipURI(const std::string &uri)
+-{
+- std::string result;
+-
+- std::string::size_type sipOffset, atOffset;
+- sipOffset = uri.find("sip:");
+- atOffset = uri.find("@");
+- if((sipOffset != std::string::npos) && (atOffset != std::string::npos))
+- {
+- result = uri.substr(sipOffset + 4, atOffset - (sipOffset + 4));
+- }
+-
+- return result;
+-}
+-
+-bool LLVoiceClient::inSpatialChannel(void)
+-{
+- bool result = false;
+-
+- if(mAudioSession)
+- result = mAudioSession->mIsSpatial;
+-
+- return result;
+-}
+-
+-std::string LLVoiceClient::getAudioSessionURI()
+-{
+- std::string result;
+-
+- if(mAudioSession)
+- result = mAudioSession->mSIPURI;
+-
+- return result;
+-}
+-
+-std::string LLVoiceClient::getAudioSessionHandle()
+-{
+- std::string result;
+-
+- if(mAudioSession)
+- result = mAudioSession->mHandle;
+-
+- return result;
+-}
+-
+-
+ /////////////////////////////
+ // Sending updates of current state
+
+@@ -5507,8 +3548,7 @@ void LLVoiceClient::updatePosition(void)
+ LLMatrix3 rot;
+ LLVector3d pos;
+
+- // TODO: If camera and avatar velocity are actually used by the voice system, we could compute them here...
+- // They're currently always set to zero.
++ // MBW -- XXX -- Setting both camera and avatar velocity to 0 for now. May figure it out later...
+
+ // Send the current camera position to the voice code
+ rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (), LLViewerCamera::getInstance()->getUpAxis());
+@@ -5523,7 +3563,7 @@ void LLVoiceClient::updatePosition(void)
+ rot = agent->getRootJoint()->getWorldRotation().getMatrix3();
+
+ pos = agent->getPositionGlobal();
+- // TODO: Can we get the head offset from outside the LLVOAvatar?
++ // MBW -- XXX -- Can we get the head offset from outside the LLVOAvatar?
+ // pos += LLVector3d(mHeadOffset);
+ pos += LLVector3d(0.f, 0.f, 1.f);
+
+@@ -5629,8 +3669,8 @@ void LLVoiceClient::setVoiceEnabled(bool enabled)
+ }
+ else
+ {
+- // Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
+- LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
++ // for now, leave active channel, to auto join when turning voice back on
++ //LLVoiceChannel::getCurrentVoiceChannel->deactivate();
+ }
+ }
+ }
+@@ -5710,34 +3750,56 @@ void LLVoiceClient::setEarLocation(S32 loc)
+
+ void LLVoiceClient::setVoiceVolume(F32 volume)
+ {
+- int scaled_volume = scale_speaker_volume(volume);
++ LL_DEBUGS("Voice") << "volume is " << volume << LL_ENDL;
+
+- if(scaled_volume != mSpeakerVolume)
++ // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
++ // Map it as follows: 0.0 -> -100, 0.5 -> 24, 1.0 -> 50
++
++ volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
++ int scaledVolume = 24; // offset scaledVolume by its default level
++ if(volume < 0.0f)
++ scaledVolume += ((int)(volume * 248.0f)); // (24 - (-100)) * 2
++ else
++ scaledVolume += ((int)(volume * 52.0f)); // (50 - 24) * 2
++
++ if(scaledVolume != mSpeakerVolume)
+ {
+- if((scaled_volume == 0) || (mSpeakerVolume == 0))
++ if((scaledVolume == -100) || (mSpeakerVolume == -100))
+ {
+ mSpeakerMuteDirty = true;
+ }
+
+- mSpeakerVolume = scaled_volume;
++ mSpeakerVolume = scaledVolume;
+ mSpeakerVolumeDirty = true;
+ }
+ }
+
+ void LLVoiceClient::setMicGain(F32 volume)
+ {
+- int scaled_volume = scale_mic_volume(volume);
+-
+- if(scaled_volume != mMicVolume)
++ int scaledVolume = ((int)(volume * 100.0f)) - 100;
++ if(scaledVolume != mMicVolume)
+ {
+- mMicVolume = scaled_volume;
++ mMicVolume = scaledVolume;
+ mMicVolumeDirty = true;
+ }
+ }
+
++void LLVoiceClient::setVivoxDebugServerName(std::string &serverName)
++{
++ if(!mAccountServerName.empty())
++ {
++ // The name has been filled in already, which means we know whether we're connecting to agni or not.
++ if(!sConnectingToAgni)
++ {
++ // Only use the setting if we're connecting to a development grid -- always use bhr when on agni.
++ mAccountServerName = serverName;
++ }
++ }
++}
++
+ void LLVoiceClient::keyDown(KEY key, MASK mask)
+ {
+-// LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
++ LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
+
+ if (gKeyboard->getKeyRepeated(key))
+ {
+@@ -5875,6 +3937,19 @@ BOOL LLVoiceClient::getUsingPTT(const LLUUID& id)
+ return result;
+ }
+
++BOOL LLVoiceClient::getPTTPressed(const LLUUID& id)
++{
++ BOOL result = FALSE;
++
++ participantState *participant = findParticipantByID(id);
++ if(participant)
++ {
++ result = participant->mPTT;
++ }
++
++ return result;
++}
++
+ BOOL LLVoiceClient::getOnMuteList(const LLUUID& id)
+ {
+ BOOL result = FALSE;
+@@ -5906,841 +3981,144 @@ F32 LLVoiceClient::getUserVolume(const LLUUID& id)
+
+ void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
+ {
+- if(mAudioSession)
+- {
+- participantState *participant = findParticipantByID(id);
+- if (participant)
+- {
+- // volume can amplify by as much as 4x!
+- S32 ivol = (S32)(400.f * volume * volume);
+- participant->mUserVolume = llclamp(ivol, 0, 400);
+- participant->mVolumeDirty = TRUE;
+- mAudioSession->mVolumeDirty = TRUE;
+- }
+- }
+-}
+-
+-std::string LLVoiceClient::getGroupID(const LLUUID& id)
+-{
+- std::string result;
+-
+ participantState *participant = findParticipantByID(id);
+- if(participant)
++ if (participant)
+ {
+- result = participant->mGroupID;
++ // volume can amplify by as much as 4x!
++ S32 ivol = (S32)(400.f * volume * volume);
++ participant->mUserVolume = llclamp(ivol, 0, 400);
++ participant->mVolumeDirty = TRUE;
++ mVolumeDirty = TRUE;
+ }
+-
+- return result;
+ }
+
+-BOOL LLVoiceClient::getAreaVoiceDisabled()
+-{
+- return mAreaVoiceDisabled;
+-}
+-
+-void LLVoiceClient::recordingLoopStart(int seconds, int deltaFramesPerControlFrame)
+-{
+-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Start)" << LL_ENDL;
+-
+- if(!mMainSessionGroupHandle.empty())
+- {
+- std::ostringstream stream;
+- stream
+- << ""
+- << "" << mMainSessionGroupHandle << ""
+- << "Start"
+- << "" << deltaFramesPerControlFrame << ""
+- << "" << "" << ""
+- << "false"
+- << "" << seconds << ""
+- << "\n\n\n";
+
+
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::recordingLoopSave(const std::string& filename)
++LLVoiceClient::serviceType LLVoiceClient::getServiceType(const LLUUID& id)
+ {
+-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Flush)" << LL_ENDL;
++ serviceType result = serviceTypeUnknown;
+
+- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
+- {
+- std::ostringstream stream;
+- stream
+- << ""
+- << "" << mMainSessionGroupHandle << ""
+- << "Flush"
+- << "" << filename << ""
+- << "\n\n\n";
+-
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::recordingStop()
+-{
+-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Stop)" << LL_ENDL;
+-
+- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
+- {
+- std::ostringstream stream;
+- stream
+- << ""
+- << "" << mMainSessionGroupHandle << ""
+- << "Stop"
+- << "\n\n\n";
+-
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::filePlaybackStart(const std::string& filename)
+-{
+-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Start)" << LL_ENDL;
+-
+- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
+- {
+- std::ostringstream stream;
+- stream
+- << ""
+- << "" << mMainSessionGroupHandle << ""
+- << "Start"
+- << "" << filename << ""
+- << "\n\n\n";
+-
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::filePlaybackStop()
+-{
+-// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Stop)" << LL_ENDL;
+-
+- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
+- {
+- std::ostringstream stream;
+- stream
+- << ""
+- << "" << mMainSessionGroupHandle << ""
+- << "Stop"
+- << "\n\n\n";
+-
+- writeString(stream.str());
+- }
+-}
+-
+-void LLVoiceClient::filePlaybackSetPaused(bool paused)
+-{
+- // TODO: Implement once Vivox gives me a sample
+-}
+-
+-void LLVoiceClient::filePlaybackSetMode(bool vox, float speed)
+-{
+- // TODO: Implement once Vivox gives me a sample
+-}
+-
+-LLVoiceClient::sessionState::sessionState() :
+- mMediaStreamState(streamStateUnknown),
+- mTextStreamState(streamStateUnknown),
+- mCreateInProgress(false),
+- mMediaConnectInProgress(false),
+- mVoiceInvitePending(false),
+- mTextInvitePending(false),
+- mSynthesizedCallerID(false),
+- mIsChannel(false),
+- mIsSpatial(false),
+- mIsP2P(false),
+- mIncoming(false),
+- mVoiceEnabled(false),
+- mReconnect(false),
+- mVolumeDirty(false),
+- mParticipantsChanged(false)
+-{
+-}
+-
+-LLVoiceClient::sessionState::~sessionState()
+-{
+- removeAllParticipants();
+-}
+-
+-LLVoiceClient::sessionIterator LLVoiceClient::sessionsBegin(void)
+-{
+- return mSessions.begin();
+-}
+-
+-LLVoiceClient::sessionIterator LLVoiceClient::sessionsEnd(void)
+-{
+- return mSessions.end();
+-}
+-
+-
+-LLVoiceClient::sessionState *LLVoiceClient::findSession(const std::string &handle)
+-{
+- sessionState *result = NULL;
+- sessionMap::iterator iter = mSessionsByHandle.find(&handle);
+- if(iter != mSessionsByHandle.end())
+- {
+- result = iter->second;
+- }
+-
+- return result;
+-}
+-
+-LLVoiceClient::sessionState *LLVoiceClient::findSessionBeingCreatedByURI(const std::string &uri)
+-{
+- sessionState *result = NULL;
+- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+- {
+- sessionState *session = *iter;
+- if(session->mCreateInProgress && (session->mSIPURI == uri))
+- {
+- result = session;
+- break;
+- }
+- }
+-
+- return result;
+-}
+-
+-LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participant_id)
+-{
+- sessionState *result = NULL;
+-
+- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+- {
+- sessionState *session = *iter;
+- if(session->mCallerID == participant_id)
+- {
+- result = session;
+- break;
+- }
+- }
+-
+- return result;
+-}
+-
+-LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, const std::string &handle)
+-{
+- sessionState *result = NULL;
+-
+- if(handle.empty())
+- {
+- // No handle supplied.
+- // Check whether there's already a session with this URI
+- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+- {
+- sessionState *s = *iter;
+- if((s->mSIPURI == uri) || (s->mAlternateSIPURI == uri))
+- {
+- // TODO: I need to think about this logic... it's possible that this case should raise an internal error.
+- result = s;
+- break;
+- }
+- }
+- }
+- else // (!handle.empty())
+- {
+- // Check for an existing session with this handle
+- sessionMap::iterator iter = mSessionsByHandle.find(&handle);
+-
+- if(iter != mSessionsByHandle.end())
+- {
+- result = iter->second;
+- }
+- }
+-
+- if(!result)
+- {
+- // No existing session found.
+-
+- LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL;
+- result = new sessionState();
+- result->mSIPURI = uri;
+- result->mHandle = handle;
+-
+- mSessions.insert(result);
+-
+- if(!result->mHandle.empty())
+- {
+- mSessionsByHandle.insert(sessionMap::value_type(&(result->mHandle), result));
+- }
+- }
+- else
+- {
+- // Found an existing session
+-
+- if(uri != result->mSIPURI)
+- {
+- // TODO: Should this be an internal error?
+- LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL;
+- setSessionURI(result, uri);
+- }
+-
+- if(handle != result->mHandle)
+- {
+- // TODO: Should this be an internal error?
+- LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL;
+- setSessionHandle(result, handle);
+- }
+-
+- LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL;
+- }
+-
+- verifySessionState();
+-
+- return result;
+-}
+-
+-void LLVoiceClient::setSessionHandle(sessionState *session, const std::string &handle)
+-{
+- // Have to remove the session from the handle-indexed map before changing the handle, or things will break badly.
+-
+- if(!session->mHandle.empty())
+- {
+- // Remove session from the map if it should have been there.
+- sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
+- if(iter != mSessionsByHandle.end())
+- {
+- if(iter->second != session)
+- {
+- LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL;
+- }
+-
+- mSessionsByHandle.erase(iter);
+- }
+- else
+- {
+- LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL;
+- }
+- }
+-
+- session->mHandle = handle;
+-
+- if(!handle.empty())
+- {
+- mSessionsByHandle.insert(sessionMap::value_type(&(session->mHandle), session));
+- }
+-
+- verifySessionState();
+-}
+-
+-void LLVoiceClient::setSessionURI(sessionState *session, const std::string &uri)
+-{
+- // There used to be a map of session URIs to sessions, which made this complex....
+- session->mSIPURI = uri;
+-
+- verifySessionState();
+-}
+-
+-void LLVoiceClient::deleteSession(sessionState *session)
+-{
+- // Remove the session from the handle map
+- if(!session->mHandle.empty())
+- {
+- sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
+- if(iter != mSessionsByHandle.end())
+- {
+- if(iter->second != session)
+- {
+- LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL
+- }
+- mSessionsByHandle.erase(iter);
+- }
+- }
+-
+- // Remove the session from the URI map
+- mSessions.erase(session);
+-
+- // At this point, the session should be unhooked from all lists and all state should be consistent.
+- verifySessionState();
+-
+- // If this is the current audio session, clean up the pointer which will soon be dangling.
+- if(mAudioSession == session)
+- {
+- mAudioSession = NULL;
+- mAudioSessionChanged = true;
+- }
+-
+- // ditto for the next audio session
+- if(mNextAudioSession == session)
+- {
+- mNextAudioSession = NULL;
+- }
+-
+- // delete the session
+- delete session;
+-}
+-
+-void LLVoiceClient::deleteAllSessions()
+-{
+- LL_DEBUGS("Voice") << "called" << LL_ENDL;
+-
+- while(!mSessions.empty())
+- {
+- deleteSession(*(sessionsBegin()));
+- }
+-
+- if(!mSessionsByHandle.empty())
+- {
+- LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL
+- }
+-}
+-
+-void LLVoiceClient::verifySessionState(void)
+-{
+- // This is mostly intended for debugging problems with session state management.
+- LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL;
+-
+- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+- {
+- sessionState *session = *iter;
+-
+- LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL;
+-
+- if(!session->mHandle.empty())
+- {
+- // every session with a non-empty handle needs to be in the handle map
+- sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle));
+- if(i2 == mSessionsByHandle.end())
+- {
+- LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL;
+- }
+- else
+- {
+- if(i2->second != session)
+- {
+- LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL;
+- }
+- }
+- }
+- }
+-
+- // check that every entry in the handle map points to a valid session in the session set
+- for(sessionMap::iterator iter = mSessionsByHandle.begin(); iter != mSessionsByHandle.end(); iter++)
+- {
+- sessionState *session = iter->second;
+- sessionIterator i2 = mSessions.find(session);
+- if(i2 == mSessions.end())
+- {
+- LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL;
+- }
+- else
+- {
+- if(session->mHandle != (*i2)->mHandle)
+- {
+- LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL;
+- }
+- }
+- }
+-}
+-
+-LLVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
+- mURI(uri)
+-{
+- mOnlineSL = false;
+- mOnlineSLim = false;
+- mCanSeeMeOnline = true;
+- mHasBlockListEntry = false;
+- mHasAutoAcceptListEntry = false;
+- mNameResolved = false;
+- mInVivoxBuddies = false;
+- mInSLFriends = false;
+- mNeedsNameUpdate = false;
+-}
+-
+-void LLVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
+-{
+- buddyListEntry *buddy = addBuddy(uri, displayName);
+- buddy->mInVivoxBuddies = true;
+-}
+-
+-LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri)
+-{
+- std::string empty;
+- buddyListEntry *buddy = addBuddy(uri, empty);
+- if(buddy->mDisplayName.empty())
+- {
+- buddy->mNameResolved = false;
+- }
+- return buddy;
+-}
+-
+-LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri, const std::string &displayName)
+-{
+- buddyListEntry *result = NULL;
+- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
+-
+- if(iter != mBuddyListMap.end())
+- {
+- // Found a matching buddy already in the map.
+- LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
+- result = iter->second;
+- }
+-
+- if(!result)
+- {
+- // participant isn't already in one list or the other.
+- LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
+- result = new buddyListEntry(uri);
+- result->mDisplayName = displayName;
+-
+- if(IDFromName(uri, result->mUUID))
+- {
+- // Extracted UUID from name successfully.
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
+- }
+-
+- mBuddyListMap.insert(buddyListMap::value_type(&(result->mURI), result));
+- }
+-
+- return result;
+-}
+-
+-LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const std::string &uri)
+-{
+- buddyListEntry *result = NULL;
+- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
+- if(iter != mBuddyListMap.end())
+- {
+- result = iter->second;
+- }
+-
+- return result;
+-}
+-
+-LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const LLUUID &id)
+-{
+- buddyListEntry *result = NULL;
+- buddyListMap::iterator iter;
+-
+- for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
++ participantState *participant = findParticipantByID(id);
++ if(participant)
+ {
+- if(iter->second->mUUID == id)
+- {
+- result = iter->second;
+- break;
+- }
++ result = participant->mServiceType;
+ }
+
+ return result;
+ }
+
+-LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddyByDisplayName(const std::string &name)
++std::string LLVoiceClient::getGroupID(const LLUUID& id)
+ {
+- buddyListEntry *result = NULL;
+- buddyListMap::iterator iter;
++ std::string result;
+
+- for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
++ participantState *participant = findParticipantByID(id);
++ if(participant)
+ {
+- if(iter->second->mDisplayName == name)
+- {
+- result = iter->second;
+- break;
+- }
++ result = participant->mGroupID;
+ }
+
+ return result;
+ }
+
+-void LLVoiceClient::deleteBuddy(const std::string &uri)
+-{
+- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
+- if(iter != mBuddyListMap.end())
+- {
+- LL_DEBUGS("Voice") << "deleting buddy " << uri << LL_ENDL;
+- buddyListEntry *buddy = iter->second;
+- mBuddyListMap.erase(iter);
+- delete buddy;
+- }
+- else
+- {
+- LL_DEBUGS("Voice") << "attempt to delete nonexistent buddy " << uri << LL_ENDL;
+- }
+-
+-}
+-
+-void LLVoiceClient::deleteAllBuddies(void)
+-{
+- while(!mBuddyListMap.empty())
+- {
+- deleteBuddy(*(mBuddyListMap.begin()->first));
+- }
+-
+- // Don't want to correlate with friends list when we've emptied the buddy list.
+- mBuddyListMapPopulated = false;
+-
+- // Don't want to correlate with friends list when we've reset the block rules.
+- mBlockRulesListReceived = false;
+- mAutoAcceptRulesListReceived = false;
+-}
+-
+-void LLVoiceClient::deleteAllBlockRules(void)
+-{
+- // Clear the block list entry flags from all local buddy list entries
+- buddyListMap::iterator buddy_it;
+- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
+- {
+- buddy_it->second->mHasBlockListEntry = false;
+- }
+-}
+-
+-void LLVoiceClient::deleteAllAutoAcceptRules(void)
+-{
+- // Clear the auto-accept list entry flags from all local buddy list entries
+- buddyListMap::iterator buddy_it;
+- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
+- {
+- buddy_it->second->mHasAutoAcceptListEntry = false;
+- }
+-}
+-
+-void LLVoiceClient::addBlockRule(const std::string &blockMask, const std::string &presenceOnly)
+-{
+- buddyListEntry *buddy = NULL;
+-
+- // blockMask is the SIP URI of a friends list entry
+- buddyListMap::iterator iter = mBuddyListMap.find(&blockMask);
+- if(iter != mBuddyListMap.end())
+- {
+- LL_DEBUGS("Voice") << "block list entry for " << blockMask << LL_ENDL;
+- buddy = iter->second;
+- }
+-
+- if(buddy == NULL)
+- {
+- LL_DEBUGS("Voice") << "block list entry for unknown buddy " << blockMask << LL_ENDL;
+- buddy = addBuddy(blockMask);
+- }
+-
+- if(buddy != NULL)
+- {
+- buddy->mHasBlockListEntry = true;
+- }
+-}
+-
+-void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy)
+-{
+- buddyListEntry *buddy = NULL;
+-
+- // blockMask is the SIP URI of a friends list entry
+- buddyListMap::iterator iter = mBuddyListMap.find(&autoAcceptMask);
+- if(iter != mBuddyListMap.end())
+- {
+- LL_DEBUGS("Voice") << "auto-accept list entry for " << autoAcceptMask << LL_ENDL;
+- buddy = iter->second;
+- }
+-
+- if(buddy == NULL)
+- {
+- LL_DEBUGS("Voice") << "auto-accept list entry for unknown buddy " << autoAcceptMask << LL_ENDL;
+- buddy = addBuddy(autoAcceptMask);
+- }
+-
+- if(buddy != NULL)
+- {
+- buddy->mHasAutoAcceptListEntry = true;
+- }
+-}
+-
+-void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
+-{
+- // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done.
+- mBlockRulesListReceived = true;
+-}
+-
+-void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString)
++BOOL LLVoiceClient::getAreaVoiceDisabled()
+ {
+- // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done.
+- mAutoAcceptRulesListReceived = true;
++ return mAreaVoiceDisabled;
+ }
+
+ void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
+ {
+- mParticipantObservers.insert(observer);
++ mObservers.insert(observer);
+ }
+
+ void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
+ {
+- mParticipantObservers.erase(observer);
++ mObservers.erase(observer);
+ }
+
+-void LLVoiceClient::notifyParticipantObservers()
++void LLVoiceClient::notifyObservers()
+ {
+- for (observer_set_t::iterator it = mParticipantObservers.begin();
+- it != mParticipantObservers.end();
++ for (observer_set_t::iterator it = mObservers.begin();
++ it != mObservers.end();
+ )
+ {
+ LLVoiceClientParticipantObserver* observer = *it;
+ observer->onChange();
+ // In case onChange() deleted an entry.
+- it = mParticipantObservers.upper_bound(observer);
++ it = mObservers.upper_bound(observer);
+ }
+ }
+
+-void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
++void LLVoiceClient::addStatusObserver(LLVoiceClientStatusObserver* observer)
+ {
+ mStatusObservers.insert(observer);
+ }
+
+-void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
++void LLVoiceClient::removeStatusObserver(LLVoiceClientStatusObserver* observer)
+ {
+ mStatusObservers.erase(observer);
+ }
+
+ void LLVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status)
+ {
+- if(mAudioSession)
++ if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
+ {
+- if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
+- {
+- switch(mAudioSession->mErrorStatusCode)
+- {
+- case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
+- case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
+- case 20715:
+- //invalid channel, we may be using a set of poorly cached
+- //info
+- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
+- break;
+- case 1009:
+- //invalid username and password
+- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
+- break;
+- }
+-
+- // Reset the error code to make sure it won't be reused later by accident.
+- mAudioSession->mErrorStatusCode = 0;
+- }
+- else if(status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL)
++ switch(mVivoxErrorStatusCode)
+ {
+- switch(mAudioSession->mErrorStatusCode)
+- {
+- case 404: // NOT_FOUND
+- case 480: // TEMPORARILY_UNAVAILABLE
+- case 408: // REQUEST_TIMEOUT
+- // call failed because other user was not available
+- // treat this as an error case
+- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
+-
+- // Reset the error code to make sure it won't be reused later by accident.
+- mAudioSession->mErrorStatusCode = 0;
+- break;
+- }
++ case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
++ case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
++ case 20715:
++ //invalid channel, we may be using a set of poorly cached
++ //info
++ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
++ break;
++ case 1009:
++ //invalid username and password
++ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
++ break;
+ }
++
++ // Reset the error code to make sure it won't be reused later by accident.
++ mVivoxErrorStatusCode = 0;
+ }
+-
+- LL_DEBUGS("Voice")
+- << " " << LLVoiceClientStatusObserver::status2string(status)
+- << ", session URI " << getAudioSessionURI()
+- << (inSpatialChannel()?", proximal is true":", proximal is false")
+- << LL_ENDL;
++
++ if (status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL
++ //NOT_FOUND || TEMPORARILY_UNAVAILABLE || REQUEST_TIMEOUT
++ && (mVivoxErrorStatusCode == 404 || mVivoxErrorStatusCode == 480 || mVivoxErrorStatusCode == 408))
++ {
++ // call failed because other user was not available
++ // treat this as an error case
++ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
++
++ // Reset the error code to make sure it won't be reused later by accident.
++ mVivoxErrorStatusCode = 0;
++ }
++
++ LL_DEBUGS("Voice") << " " << LLVoiceClientStatusObserver::status2string(status) << ", session URI " << mSessionURI << LL_ENDL;
+
+ for (status_observer_set_t::iterator it = mStatusObservers.begin();
+ it != mStatusObservers.end();
+ )
+ {
+ LLVoiceClientStatusObserver* observer = *it;
+- observer->onChange(status, getAudioSessionURI(), inSpatialChannel());
++ observer->onChange(status, mSessionURI, !mNonSpatialChannel);
+ // In case onError() deleted an entry.
+ it = mStatusObservers.upper_bound(observer);
+ }
+
+ }
+
+-void LLVoiceClient::addObserver(LLFriendObserver* observer)
+-{
+- mFriendObservers.insert(observer);
+-}
+-
+-void LLVoiceClient::removeObserver(LLFriendObserver* observer)
+-{
+- mFriendObservers.erase(observer);
+-}
+-
+-void LLVoiceClient::notifyFriendObservers()
+-{
+- for (friend_observer_set_t::iterator it = mFriendObservers.begin();
+- it != mFriendObservers.end();
+- )
+- {
+- LLFriendObserver* observer = *it;
+- it++;
+- // The only friend-related thing we notify on is online/offline transitions.
+- observer->changed(LLFriendObserver::ONLINE);
+- }
+-}
+-
+-void LLVoiceClient::lookupName(const LLUUID &id)
+-{
+- gCacheName->getName(id, onAvatarNameLookup);
+-}
+-
+ //static
+-void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
+-{
+- if(gVoiceClient)
+- {
+- std::string name = llformat("%s %s", first.c_str(), last.c_str());
+- gVoiceClient->avatarNameResolved(id, name);
+- }
+-}
++// void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
++// {
++// participantState* statep = gVoiceClient->findParticipantByID(id);
+
+-void LLVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
+-{
+- // If the avatar whose name just resolved is on our friends list, resync the friends list.
+- if(LLAvatarTracker::instance().getBuddyInfo(id) != NULL)
+- {
+- mFriendsListDirty = true;
+- }
++// if (statep)
++// {
++// statep->mDisplayName = first + " " + last;
++// }
+
+- // Iterate over all sessions.
+- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+- {
+- sessionState *session = *iter;
+-
+- // Check for this user as a participant in this session
+- participantState *participant = session->findParticipantByID(id);
+- if(participant)
+- {
+- // Found -- fill in the name
+- participant->mAccountName = name;
+- // and post a "participants updated" message to listeners later.
+- session->mParticipantsChanged = true;
+- }
+-
+- // Check whether this is a p2p session whose caller name just resolved
+- if(session->mCallerID == id)
+- {
+- // this session's "caller ID" just resolved. Fill in the name.
+- session->mName = name;
+- if(session->mTextInvitePending)
+- {
+- session->mTextInvitePending = false;
+-
+- // We don't need to call gIMMgr->addP2PSession() here. The first incoming message will create the panel.
+- }
+- if(session->mVoiceInvitePending)
+- {
+- session->mVoiceInvitePending = false;
+-
+- gIMMgr->inviteToSession(
+- session->mIMSessionID,
+- session->mName,
+- session->mCallerID,
+- session->mName,
+- IM_SESSION_P2P_INVITE,
+- LLIMMgr::INVITATION_TYPE_VOICE,
+- session->mHandle,
+- session->mSIPURI);
+- }
+-
+- }
+- }
+-}
++// gVoiceClient->notifyObservers();
++// }
+
+ class LLViewerParcelVoiceInfo : public LLHTTPNode
+ {
+diff --git a/linden/indra/newview/llvoiceclient.h b/linden/indra/newview/llvoiceclient.h
+index 13dd974..d0b7839 100644
+--- a/linden/indra/newview/llvoiceclient.h
++++ b/linden/indra/newview/llvoiceclient.h
+@@ -41,7 +41,6 @@ class LLVivoxProtocolParser;
+ #include "v3math.h"
+ #include "llframetimer.h"
+ #include "llviewerregion.h"
+-#include "llcallingcard.h" // for LLFriendObserver
+
+ class LLVoiceClientParticipantObserver
+ {
+@@ -92,10 +91,41 @@ class LLVoiceClient: public LLSingleton
+
+ public:
+
++ enum serviceType
++ {
++ serviceTypeUnknown, // Unknown, returned if no data on the avatar is available
++ serviceTypeA, // spatialized local chat
++ serviceTypeB, // remote multi-party chat
++ serviceTypeC // one-to-one and small group chat
++ };
+ static F32 OVERDRIVEN_POWER_LEVEL;
+
+ void updateSettings(); // call after loading settings and whenever they change
+
++ /////////////////////////////
++ // session control messages
++ void connect();
++
++ void connectorCreate();
++ void connectorShutdown();
++
++ void requestVoiceAccountProvision(S32 retries = 3);
++ void userAuthorized(
++ const std::string& firstName,
++ const std::string& lastName,
++ const LLUUID &agentID);
++ void login(const std::string& accountName, const std::string &password);
++ void loginSendMessage();
++ void logout();
++ void logoutSendMessage();
++
++ void channelGetListSendMessage();
++ void sessionCreateSendMessage();
++ void sessionConnectSendMessage();
++ void sessionTerminate();
++ void sessionTerminateSendMessage();
++ void sessionTerminateByHandle(std::string &sessionHandle);
++
+ void getCaptureDevicesSendMessage();
+ void getRenderDevicesSendMessage();
+
+@@ -140,32 +170,23 @@ class LLVoiceClient: public LLSingleton
+
+ /////////////////////////////
+ // Response/Event handlers
+- void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
+- void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases);
+- void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
+- void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
+- void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString);
++ void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle);
++ void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle);
++ void channelGetListResponse(int statusCode, std::string &statusString);
++ void sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle);
++ void sessionConnectResponse(int statusCode, std::string &statusString);
++ void sessionTerminateResponse(int statusCode, std::string &statusString);
+ void logoutResponse(int statusCode, std::string &statusString);
+ void connectorShutdownResponse(int statusCode, std::string &statusString);
+
+- void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
+- void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);
+- void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming);
+- void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString);
+- void sessionGroupAddedEvent(std::string &sessionGroupHandle);
+- void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle);
+- void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType);
+- void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString);
+- void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
++ void loginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
++ void sessionNewEvent(std::string &accountHandle, std::string &eventSessionHandle, int state, std::string &nameString, std::string &uriString);
++ void sessionStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, std::string &sessionHandle, int state, bool isChannel, std::string &nameString);
++ void participantStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, int state, std::string &nameString, std::string &displayNameString, int participantType);
++ void participantPropertiesEvent(std::string &uriString, int statusCode, std::string &statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
+ void auxAudioPropertiesEvent(F32 energy);
+- void buddyPresenceEvent(std::string &uriString, std::string &alias, std::string &statusString, std::string &applicationString);
+- void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
+- void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string ¬ificationType);
+- void subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType);
+-
+- void buddyListChanged();
++
+ void muteListChanged();
+- void updateFriends(U32 mask);
+
+ /////////////////////////////
+ // Sending updates of current state
+@@ -189,6 +210,7 @@ static void updatePosition(void);
+ void setVoiceVolume(F32 volume);
+ void setMicGain(F32 volume);
+ void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
++ void setVivoxDebugServerName(std::string &serverName);
+ void setLipSyncEnabled(BOOL enabled);
+ BOOL lipSyncEnabled();
+
+@@ -203,261 +225,57 @@ static void updatePosition(void);
+ BOOL getIsSpeaking(const LLUUID& id);
+ BOOL getIsModeratorMuted(const LLUUID& id);
+ F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
++ BOOL getPTTPressed(const LLUUID& id); // This is the inverse of the "locally muted" property.
+ BOOL getOnMuteList(const LLUUID& id);
+ F32 getUserVolume(const LLUUID& id);
+ std::string getDisplayName(const LLUUID& id);
+
+ // MBW -- XXX -- Not sure how to get this data out of the TVC
+ BOOL getUsingPTT(const LLUUID& id);
++ serviceType getServiceType(const LLUUID& id); // type of chat the user is involved in (see bHear scope doc for definitions of A/B/C)
+ std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable)
+
+ /////////////////////////////
+ BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled.
+ // Use this to determine whether to show a "no speech" icon in the menu bar.
+-
+- /////////////////////////////
+- // Recording controls
+- void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
+- void recordingLoopSave(const std::string& filename);
+- void recordingStop();
+-
+- // Playback controls
+- void filePlaybackStart(const std::string& filename);
+- void filePlaybackStop();
+- void filePlaybackSetPaused(bool paused);
+- void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
+-
+-
+- // This is used by the string-keyed maps below, to avoid storing the string twice.
+- // The 'const std::string *' in the key points to a string actually stored in the object referenced by the map.
+- // The add and delete operations for each map allocate and delete in the right order to avoid dangling references.
+- // The default compare operation would just compare pointers, which is incorrect, so they must use this comparitor instead.
+- struct stringMapComparitor
+- {
+- bool operator()(const std::string* a, const std::string * b) const
+- {
+- return a->compare(*b) < 0;
+- }
+- };
+
+- struct uuidMapComparitor
+- {
+- bool operator()(const LLUUID* a, const LLUUID * b) const
+- {
+- return *a < *b;
+- }
+- };
+-
+ struct participantState
+ {
+ public:
+ participantState(const std::string &uri);
+-
+- bool updateMuteState();
+-
+ std::string mURI;
+- LLUUID mAvatarID;
+- std::string mAccountName;
++ std::string mName;
+ std::string mDisplayName;
++ bool mPTT;
++ bool mIsSpeaking;
++ bool mIsModeratorMuted;
+ LLFrameTimer mSpeakingTimeout;
+ F32 mLastSpokeTimestamp;
+ F32 mPower;
+ int mVolume;
++ serviceType mServiceType;
+ std::string mGroupID;
+- int mUserVolume;
+- bool mPTT;
+- bool mIsSpeaking;
+- bool mIsModeratorMuted;
+ bool mOnMuteList; // true if this avatar is on the user's mute list (and should be muted)
++ int mUserVolume;
+ bool mVolumeDirty; // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
+ bool mAvatarIDValid;
+- bool mIsSelf;
+- };
+- typedef std::map participantMap;
+-
+- typedef std::map participantUUIDMap;
+-
+- enum streamState
+- {
+- streamStateUnknown = 0,
+- streamStateIdle = 1,
+- streamStateConnected = 2,
+- streamStateRinging = 3,
++ LLUUID mAvatarID;
+ };
++ typedef std::map participantMap;
+
+- struct sessionState
+- {
+- public:
+- sessionState();
+- ~sessionState();
+-
+- participantState *addParticipant(const std::string &uri);
+- // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
+- // Take care not to use the pointer again after that.
+- void removeParticipant(participantState *participant);
+- void removeAllParticipants();
+-
+- participantState *findParticipant(const std::string &uri);
+- participantState *findParticipantByID(const LLUUID& id);
+-
+- std::string mHandle;
+- std::string mGroupHandle;
+- std::string mSIPURI;
+- std::string mAlias;
+- std::string mName;
+- std::string mAlternateSIPURI;
+- std::string mHash; // Channel password
+- std::string mErrorStatusString;
+- std::queue mTextMsgQueue;
+-
+- LLUUID mIMSessionID;
+- LLUUID mCallerID;
+- int mErrorStatusCode;
+- int mMediaStreamState;
+- int mTextStreamState;
+- bool mCreateInProgress; // True if a Session.Create has been sent for this session and no response has been received yet.
+- bool mMediaConnectInProgress; // True if a Session.MediaConnect has been sent for this session and no response has been received yet.
+- bool mVoiceInvitePending; // True if a voice invite is pending for this session (usually waiting on a name lookup)
+- bool mTextInvitePending; // True if a text invite is pending for this session (usually waiting on a name lookup)
+- bool mSynthesizedCallerID; // True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup.
+- bool mIsChannel; // True for both group and spatial channels (false for p2p, PSTN)
+- bool mIsSpatial; // True for spatial channels
+- bool mIsP2P;
+- bool mIncoming;
+- bool mVoiceEnabled;
+- bool mReconnect; // Whether we should try to reconnect to this session if it's dropped
+- // Set to true when the mute state of someone in the participant list changes.
+- // The code will have to walk the list to find the changed participant(s).
+- bool mVolumeDirty;
+-
+- bool mParticipantsChanged;
+- participantMap mParticipantsByURI;
+- participantUUIDMap mParticipantsByUUID;
+- };
+-
++ participantState *findParticipant(const std::string &uri);
++ participantState *findParticipantByAvatar(LLVOAvatar *avatar);
+ participantState *findParticipantByID(const LLUUID& id);
+- participantMap *getParticipantList(void);
+-
+- typedef std::map sessionMap;
+- typedef std::set sessionSet;
+-
+- typedef sessionSet::iterator sessionIterator;
+- sessionIterator sessionsBegin(void);
+- sessionIterator sessionsEnd(void);
+-
+- sessionState *findSession(const std::string &handle);
+- sessionState *findSessionBeingCreatedByURI(const std::string &uri);
+- sessionState *findSession(const LLUUID &participant_id);
+- sessionState *findSessionByCreateID(const std::string &create_id);
+-
+- sessionState *addSession(const std::string &uri, const std::string &handle = LLStringUtil::null);
+- void setSessionHandle(sessionState *session, const std::string &handle = LLStringUtil::null);
+- void setSessionURI(sessionState *session, const std::string &uri);
+- void deleteSession(sessionState *session);
+- void deleteAllSessions(void);
+-
+- void verifySessionState(void);
+-
+- void joinedAudioSession(sessionState *session);
+- void leftAudioSession(sessionState *session);
+-
+- // This is called in several places where the session _may_ need to be deleted.
+- // It contains logic for whether to delete the session or keep it around.
+- void reapSession(sessionState *session);
+-
+- // Returns true if the session seems to indicate we've moved to a region on a different voice server
+- bool sessionNeedsRelog(sessionState *session);
+-
+- struct buddyListEntry
+- {
+- buddyListEntry(const std::string &uri);
+- std::string mURI;
+- std::string mDisplayName;
+- LLUUID mUUID;
+- bool mOnlineSL;
+- bool mOnlineSLim;
+- bool mCanSeeMeOnline;
+- bool mHasBlockListEntry;
+- bool mHasAutoAcceptListEntry;
+- bool mNameResolved;
+- bool mInSLFriends;
+- bool mInVivoxBuddies;
+- bool mNeedsNameUpdate;
+- };
+-
+- typedef std::map buddyListMap;
+
+- // This should be called when parsing a buddy list entry sent by SLVoice.
+- void processBuddyListEntry(const std::string &uri, const std::string &displayName);
+-
+- buddyListEntry *addBuddy(const std::string &uri);
+- buddyListEntry *addBuddy(const std::string &uri, const std::string &displayName);
+- buddyListEntry *findBuddy(const std::string &uri);
+- buddyListEntry *findBuddy(const LLUUID &id);
+- buddyListEntry *findBuddyByDisplayName(const std::string &name);
+- void deleteBuddy(const std::string &uri);
+- void deleteAllBuddies(void);
+-
+- void deleteAllBlockRules(void);
+- void addBlockRule(const std::string &blockMask, const std::string &presenceOnly);
+- 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);
+-
+- /////////////////////////////
+- // session control messages
+- void connectorCreate();
+- void connectorShutdown();
+-
+- void requestVoiceAccountProvision(S32 retries = 3);
+- void userAuthorized(
+- const std::string& firstName,
+- const std::string& lastName,
+- const LLUUID &agentID);
+- void login(
+- const std::string& account_name,
+- const std::string& password,
+- const std::string& voice_sip_uri_hostname,
+- const std::string& voice_account_server_uri);
+- void loginSendMessage();
+- void logout();
+- void logoutSendMessage();
+-
+- void accountListBlockRulesSendMessage();
+- void accountListAutoAcceptRulesSendMessage();
+-
+- 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 sessionTerminateSendMessage(sessionState *session);
+- void sessionMediaDisconnectSendMessage(sessionState *session);
+- void sessionTextDisconnectSendMessage(sessionState *session);
++ participantMap *getParticipantList(void);
+
+- // Pokes the state machine to leave the audio session next time around.
+- void sessionTerminate();
+-
+- // Pokes the state machine to shut down the connector and restart it.
+- void requestRelog();
+-
+- // Does the actual work to get out of the audio session
+- void leaveAudioSession();
+-
+ void addObserver(LLVoiceClientParticipantObserver* observer);
+ void removeObserver(LLVoiceClientParticipantObserver* observer);
+
+- void addObserver(LLVoiceClientStatusObserver* observer);
+- void removeObserver(LLVoiceClientStatusObserver* observer);
+-
+- void addObserver(LLFriendObserver* observer);
+- void removeObserver(LLFriendObserver* observer);
+-
+- void lookupName(const LLUUID &id);
+- static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
+- void avatarNameResolved(const LLUUID &id, const std::string &name);
++ void addStatusObserver(LLVoiceClientStatusObserver* observer);
++ void removeStatusObserver(LLVoiceClientStatusObserver* observer);
+
++// static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
+ typedef std::vector deviceList;
+
+ deviceList *getCaptureDevices();
+@@ -469,16 +287,8 @@ static void updatePosition(void);
+ void setSpatialChannel(
+ const std::string &uri,
+ const std::string &credentials);
+- // start a voice session with the specified user
+- void callUser(const LLUUID &uuid);
+-
+- // Send a text message to the specified user, initiating the session if necessary.
+- bool sendTextMessage(const LLUUID& participant_id, const std::string& message);
+-
+- // close any existing text IM session with the specified user
+- void endUserIMSession(const LLUUID &uuid);
+-
+- bool answerInvite(std::string &sessionHandle);
++ void callUser(LLUUID &uuid);
++ void answerInvite(std::string &sessionHandle, LLUUID& other_user_id);
+ void declineInvite(std::string &sessionHandle);
+ void leaveNonSpatialChannel();
+
+@@ -491,37 +301,33 @@ static void updatePosition(void);
+ bool inProximalChannel();
+
+ std::string sipURIFromID(const LLUUID &id);
+-
+- // Returns true if the indicated user is online via SIP presence according to SLVoice.
+- // Note that we only get SIP presence data for other users that are in our vivox buddy list.
+- bool isOnlineSIP(const LLUUID &id);
+-
++
+ private:
+
+ // internal state for a simple state machine. This is used to deal with the asynchronous nature of some of the messages.
+ // Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string().
+ enum state
+ {
+- stateDisableCleanup,
+ stateDisabled, // Voice is turned off.
+ stateStart, // Class is initialized, socket is created
+ stateDaemonLaunched, // Daemon has been launched
+ stateConnecting, // connect() call has been issued
+- stateConnected, // connection to the daemon has been made, send some initial setup commands.
+ stateIdle, // socket is connected, ready for messaging
+- stateMicTuningStart,
+- stateMicTuningRunning,
+- stateMicTuningStop,
+ stateConnectorStart, // connector needs to be started
+ stateConnectorStarting, // waiting for connector handle
+ stateConnectorStarted, // connector handle received
++ stateMicTuningNoLogin, // mic tuning before login
+ stateLoginRetry, // need to retry login (failed due to changing password)
+ stateLoginRetryWait, // waiting for retry timer
+ stateNeedsLogin, // send login request
+ stateLoggingIn, // waiting for account handle
+ stateLoggedIn, // account handle received
+- stateCreatingSessionGroup, // Creating the main session group
+ stateNoChannel, //
++ stateMicTuningStart,
++ stateMicTuningRunning,
++ stateMicTuningStop,
++ stateSessionCreate, // need to send Session.Create command
++ stateSessionConnect, // need to send Session.Connect command
+ stateJoiningSession, // waiting for session handle
+ stateSessionJoined, // session handle received
+ stateRunning, // in session, steady state
+@@ -548,7 +354,7 @@ static void updatePosition(void);
+
+ state mState;
+ bool mSessionTerminateRequested;
+- bool mRelogRequested;
++ bool mNonSpatialChannel;
+
+ void setState(state inState);
+ state getState(void) { return mState; };
+@@ -571,7 +377,18 @@ static void updatePosition(void);
+ std::string mAccountDisplayName;
+ std::string mAccountFirstName;
+ std::string mAccountLastName;
+-
++
++ std::string mNextP2PSessionURI; // URI of the P2P session to join next
++ std::string mNextSessionURI; // URI of the session to join next
++ std::string mNextSessionHandle; // Session handle of the session to join next
++ std::string mNextSessionHash; // Password hash for the session to join next
++ bool mNextSessionSpatial; // Will next session be a spatial chat?
++ bool mNextSessionNoReconnect; // Next session should not auto-reconnect (i.e. user -> user chat)
++ bool mNextSessionResetOnClose; // If this is true, go back to spatial chat when the next session terminates.
++
++ std::string mSessionStateEventHandle; // session handle received in SessionStateChangeEvents
++ std::string mSessionStateEventURI; // session URI received in SessionStateChangeEvents
++
+ bool mTuningMode;
+ float mTuningEnergy;
+ std::string mTuningAudioFile;
+@@ -582,40 +399,32 @@ static void updatePosition(void);
+ state mTuningExitState; // state to return to when we leave tuning mode.
+
+ std::string mSpatialSessionURI;
+- std::string mSpatialSessionCredentials;
+-
+- std::string mMainSessionGroupHandle; // handle of the "main" session group.
++
++ bool mSessionResetOnClose;
++
++ int mVivoxErrorStatusCode;
++ std::string mVivoxErrorStatusString;
+
+ std::string mChannelName; // Name of the channel to be looked up
+ bool mAreaVoiceDisabled;
+- sessionState *mAudioSession; // Session state for the current audio session
+- bool mAudioSessionChanged; // set to true when the above pointer gets changed, so observers can be notified.
+-
+- sessionState *mNextAudioSession; // Session state for the audio session we're trying to join
+-
+-// std::string mSessionURI; // URI of the session we're in.
+-// std::string mSessionHandle; // returned by ?
++ std::string mSessionURI; // URI of the session we're in.
++ bool mSessionP2P; // true if this session is a p2p call
+
+ S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings
+ std::string mCurrentRegionName; // Used to detect parcel boundary crossings
+
+ std::string mConnectorHandle; // returned by "Create Connector" message
+ std::string mAccountHandle; // returned by login message
+- int mNumberOfAliases;
++ std::string mSessionHandle; // returned by ?
+ U32 mCommandCookie;
+
+- std::string mVoiceAccountServerURI;
+- std::string mVoiceSIPURIHostName;
++ std::string mAccountServerName;
++ std::string mAccountServerURI;
+
+ int mLoginRetryCount;
+
+- sessionMap mSessionsByHandle; // Active sessions, indexed by session handle. Sessions which are being initiated may not be in this map.
+- sessionSet mSessions; // All sessions, not indexed. This is the canonical session list.
+-
+- bool mBuddyListMapPopulated;
+- bool mBlockRulesListReceived;
+- bool mAutoAcceptRulesListReceived;
+- buddyListMap mBuddyListMap;
++ participantMap mParticipantMap;
++ bool mParticipantMapChanged;
+
+ deviceList mCaptureDevices;
+ deviceList mRenderDevices;
+@@ -625,41 +434,40 @@ static void updatePosition(void);
+ bool mCaptureDeviceDirty;
+ bool mRenderDeviceDirty;
+
++ participantState *addParticipant(const std::string &uri);
++ // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
++ // Take care not to use the pointer again after that.
++ void removeParticipant(participantState *participant);
++ void removeAllParticipants();
++
++ void updateMuteState(participantState *participant);
++
++ typedef std::map channelMap;
++ channelMap mChannelMap;
++
++ // These are used by the parser when processing a channel list response.
++ void clearChannelMap(void);
++ void addChannelMapEntry(std::string &name, std::string &uri);
++ std::string findChannelURI(std::string &name);
++
+ // 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 joinSession(sessionState *session);
++ void switchChannel(std::string uri = std::string(), bool spatial = true, bool noReconnect = false, std::string hash = "");
++ void joinSession(std::string handle, std::string uri);
+
+-static std::string nameFromAvatar(LLVOAvatar *avatar);
+-static std::string nameFromID(const LLUUID &id);
+-static bool IDFromName(const std::string name, LLUUID &uuid);
+-static std::string displayNameFromAvatar(LLVOAvatar *avatar);
++ std::string nameFromAvatar(LLVOAvatar *avatar);
++ std::string nameFromID(const LLUUID &id);
++ bool IDFromName(const std::string name, LLUUID &uuid);
++ std::string displayNameFromAvatar(LLVOAvatar *avatar);
+ std::string sipURIFromAvatar(LLVOAvatar *avatar);
+ std::string sipURIFromName(std::string &name);
+-
+- // Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
+-static std::string nameFromsipURI(const std::string &uri);
+-
+- bool inSpatialChannel(void);
+- std::string getAudioSessionURI();
+- std::string getAudioSessionHandle();
+
+ void sendPositionalUpdate(void);
+
+ void buildSetCaptureDevice(std::ostringstream &stream);
+ void buildSetRenderDevice(std::ostringstream &stream);
+- void buildLocalAudioUpdates(std::ostringstream &stream);
+-
+- void clearAllLists();
+- void checkFriend(const LLUUID& id);
+- void sendFriendsListUpdates();
+-
+- // start a text IM session with the specified user
+- // This will be asynchronous, the session may be established at a future time.
+- sessionState* startUserIMSession(const LLUUID& uuid);
+- void sendQueuedTextMessages(sessionState *session);
+
+ void enforceTether(void);
+
+@@ -683,9 +491,10 @@ static std::string nameFromsipURI(const std::string &uri);
+ bool mPTTIsToggle;
+ bool mUserPTTState;
+ bool mMuteMic;
+-
+- // Set to true when the friends list is known to have changed.
+- bool mFriendsListDirty;
++
++ // Set to true when the mute state of someone in the participant list changes.
++ // The code will have to walk the list to find the changed participant(s).
++ bool mVolumeDirty;
+
+ enum
+ {
+@@ -713,18 +522,14 @@ static std::string nameFromsipURI(const std::string &uri);
+ BOOL mLipSyncEnabled;
+
+ typedef std::set observer_set_t;
+- observer_set_t mParticipantObservers;
++ observer_set_t mObservers;
+
+- void notifyParticipantObservers();
++ void notifyObservers();
+
+ typedef std::set status_observer_set_t;
+ status_observer_set_t mStatusObservers;
+
+ void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
+-
+- typedef std::set friend_observer_set_t;
+- friend_observer_set_t mFriendObservers;
+- void notifyFriendObservers();
+ };
+
+ extern LLVoiceClient *gVoiceClient;
diff --git a/stack_trace.log b/stack_trace.log
new file mode 100644
index 0000000..b04e344
--- /dev/null
+++ b/stack_trace.log
@@ -0,0 +1,32 @@
+0: ELF(do_elfio_glibc_backtrace()+0x424) [0x9962c13]
+1: ELF(LLAppViewerLinux::handleSyncCrashTrace()+0xb) [0x9963533]
+2: ELF(LLAppViewer::handleSyncViewerCrash()+0x20) [0x85181a2]
+3: ELF(LLApp::runSyncErrorHandler()+0x16) [0x9e7d384]
+4: ELF(LLApp::setError()+0x17) [0x9e7d40d]
+5: ELF(default_unix_signal_handler(int, siginfo*, void*)+0xd22) [0x9e7f08e]
+6: [0xb807640c]
+7: /usr/lib/libstdc++.so.6(_ZNSs6assignERKSs+0x2b) [0xb617825b]
+8: /usr/lib/libstdc++.so.6(_ZNSsaSERKSs+0x24) [0xb6178334]
+9: ELF(attach_label(std::string&, void*)+0x32) [0x9563d7b]
+10: ELF(LLMenuItemCallGL::buildDrawLabel()+0x232) [0x9c2d012]
+11: ELF(LLMenuGL::arrange()+0xb07) [0x9c31719]
+12: ELF(LLMenuGL::append(LLMenuItemGL*)+0x4c) [0x9c280ca]
+13: ELF(LLMenuGL::arrange()+0x6b3) [0x9c312c5]
+14: ELF(LLMenuGL::append(LLMenuItemGL*)+0x4c) [0x9c280ca]
+15: ELF(LLVOAvatar::buildCharacter()+0x3a8e) [0x974689c]
+16: ELF(LLVOAvatar::LLVOAvatar(LLUUID const&, unsigned char, LLViewerRegion*)+0x4140) [0x97566e4]
+17: ELF(LLViewerObject::createObject(LLUUID const&, unsigned char, LLViewerRegion*)+0x193) [0x960ab0d]
+18: ELF(LLViewerObjectList::createObject(unsigned char, LLViewerRegion*, LLUUID const&, unsigned int, LLHost const&)+0x8f) [0x961c9f3]
+19: ELF(LLViewerObjectList::processObjectUpdate(LLMessageSystem*, void**, e_object_update_type, bool, bool)+0x8d1) [0x961e83d]
+20: ELF(process_object_update(LLMessageSystem*, void**)+0x9d) [0x95ccc9e]
+21: ELF(LLMessageTemplate::callHandlerFunc(LLMessageSystem*) const+0x47) [0x9af995d]
+22: ELF(LLTemplateMessageReader::decodeData(unsigned char const*, LLHost const&)+0xcc8) [0x9b2d12c]
+23: ELF(LLTemplateMessageReader::readMessage(unsigned char const*, LLHost const&)+0x1f) [0x9b2d653]
+24: ELF(LLMessageSystem::checkMessages(long long)+0x1211) [0x9af0205]
+25: ELF(LLMessageSystem::checkAllMessages(long long, LLPumpIO*)+0x2b) [0x9af057d]
+26: ELF(LLAppViewer::idleNetwork()+0x2ab) [0x8519b85]
+27: ELF(LLAppViewer::idle()+0xd5c) [0x85355fe]
+28: ELF(LLAppViewer::mainLoop()+0x7fe) [0x8536cdc]
+29: ELF(main+0x213) [0x996433c]
+30: /lib/i686/cmov/libc.so.6(__libc_start_main+0xe5) [0xb5f45775]
+31: bin/do-not-directly-run-imprudence-bin [0x846f7e1]
--
cgit v1.1
From 8f99d24a677cde192fb604ccf5dc8afbe26f557b Mon Sep 17 00:00:00 2001
From: Armin Weatherwax
Date: Wed, 8 Jul 2009 17:42:53 +0200
Subject: Broken: relog sometimes works once; fixed inventory and avatar not
ruthed anymore.
deleted: Imprudence.log
modified: linden/indra/newview/llagent.cpp
modified: linden/indra/newview/llappviewer.cpp
modified: linden/indra/newview/llinventorymodel.cpp
modified: linden/indra/newview/llinventorymodel.h
modified: linden/indra/newview/llinventoryview.cpp
modified: linden/indra/newview/llviewerjointattachment.h
modified: linden/indra/newview/llviewermenu.cpp
deleted: mAttachedObject.diff.txt
deleted: meerkat-llmenugl.diff.txt
deleted: meerkat-message.diff.txt
deleted: meerkat-pipeline.cpp.diff.txt
deleted: meerkat-voice.diff.txt
deleted: stack_trace.log
---
Imprudence.log | 581 --
linden/indra/newview/llagent.cpp | 12 +
linden/indra/newview/llappviewer.cpp | 2 +-
linden/indra/newview/llinventorymodel.cpp | 2 +-
linden/indra/newview/llinventorymodel.h | 6 +-
linden/indra/newview/llinventoryview.cpp | 1 +
linden/indra/newview/llviewerjointattachment.h | 4 +-
linden/indra/newview/llviewermenu.cpp | 5 +
mAttachedObject.diff.txt | 16 -
meerkat-llmenugl.diff.txt | 534 --
meerkat-message.diff.txt | 1319 -----
meerkat-pipeline.cpp.diff.txt | 22 -
meerkat-voice.diff.txt | 7282 ------------------------
stack_trace.log | 32 -
14 files changed, 27 insertions(+), 9791 deletions(-)
delete mode 100644 Imprudence.log
delete mode 100644 mAttachedObject.diff.txt
delete mode 100644 meerkat-llmenugl.diff.txt
delete mode 100644 meerkat-message.diff.txt
delete mode 100644 meerkat-pipeline.cpp.diff.txt
delete mode 100644 meerkat-voice.diff.txt
delete mode 100644 stack_trace.log
diff --git a/Imprudence.log b/Imprudence.log
deleted file mode 100644
index 3bc56eb..0000000
--- a/Imprudence.log
+++ /dev/null
@@ -1,581 +0,0 @@
-2009-07-01T20:58:49Z INFO: initConfiguration: Loading settings file list/home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings_files.xml
-2009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings_crash_behavior.xml
-2009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings.xml
-2009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/settings_per_account.xml
-2009-07-01T20:58:49Z INFO: initParseCommandLine: Language de
-2009-07-01T20:58:49Z INFO: initParseCommandLine: Location DE
-2009-07-01T20:58:49Z INFO: initParseCommandLine: Variant UTF-8
-2009-07-01T20:58:49Z INFO: initConfiguration: Using command line specified settings filename: /home/aw/.imprudence/user_settings/settings_imprudence.xml
-2009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/user_settings/settings_crash_behavior.xml
-2009-07-01T20:58:49Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/user_settings/settings_imprudence.xml
-2009-07-01T20:58:49Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/user_settings/settings_per_account.xml to load.
-2009-07-01T20:58:49Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/user_settings/settings_per_account.xml - No settings found.
-2009-07-01T20:58:49Z INFO: getFontListSans: Getting system font list from FontConfig...
-2009-07-01T20:58:49Z INFO: getFontListSans: Language de
-2009-07-01T20:58:49Z INFO: getFontListSans: Location DE
-2009-07-01T20:58:49Z INFO: getFontListSans: Variant UTF-8
-2009-07-01T20:58:49Z INFO: getFontListSans: Preferring fonts of language: de
-2009-07-01T20:58:49Z INFO: getFontListSans: Using 31 system font(s).
-2009-07-01T20:58:49Z INFO: parseFile: Loading grid info file /home/aw/.imprudence/user_settings/grid_info.xml.
-2009-07-01T20:58:49Z INFO: parseData: Loading grid data.
-2009-07-01T20:58:49Z WARNING: setPlatform: Unknown platform 'Other'.
-2009-07-01T20:58:49Z INFO: parseFile: Loading grid info file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/default_grids.xml.
-2009-07-01T20:58:49Z INFO: parseUrl: Loading grid info from 'http://opensim-viewer.sourceforge.net/db/grids.php'.
-2009-07-01T20:58:49Z INFO: blockingGet: blockingGet of http://opensim-viewer.sourceforge.net/db/grids.php
-2009-07-01T20:58:51Z WARNING: setCurrentGrid: Unknown grid ''. Setting to default grid.
-2009-07-01T20:58:51Z INFO: initMarkerFile: Last exec LLError crashed, setting LastExecEvent to 2
-2009-07-01T20:58:51Z INFO: initMarkerFile: Last exec crashed, setting LastExecEvent to 3
-2009-07-01T20:58:51Z INFO: writeSystemInfo:
-2009-07-01T20:58:51Z INFO: writeSystemInfo: Local time: 2009-07-01T22:58:51 CEST
-2009-07-01T20:58:51Z INFO: writeSystemInfo: CPU info:
-processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 14 model name : Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz stepping : 12 cpu MHz : 798.000 cache size : 2048 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe constant_tsc arch_perfmon bts pni monitor est tm2 xtpr pdcm bogomips : 3990.13 clflush size : 64 power management: processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 14 model name : Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz stepping : 12 cpu MHz : 798.000 cache size : 2048 KB physical id : 0 siblings : 2 core id : 1 cpu cores : 2 apicid : 1 initial apicid : 1 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe constant_tsc arch_perfmon bts pni monitor est tm2 xtpr pdcm bogomips : 3990.49 clflush size : 64 power management:
-->mHasSSE: 1
-->mHasSSE2: 1
-->mHasAltivec: 0
-->mCPUMhz: 798
-->mCPUString: Intel(R) Core(TM) Duo CPU T2450 @ 2.00GHz
-
-2009-07-01T20:58:51Z INFO: writeSystemInfo: Memory info:
-MemTotal: 1945568 kB MemFree: 593720 kB Buffers: 13392 kB Cached: 580556 kB SwapCached: 2340 kB Active: 79892 kB Inactive: 810692 kB Active(anon): 17656 kB Inactive(anon): 280332 kB Active(file): 62236 kB Inactive(file): 530360 kB Unevictable: 0 kB Mlocked: 0 kB HighTotal: 1056424 kB HighFree: 133548 kB LowTotal: 889144 kB LowFree: 460172 kB SwapTotal: 995988 kB SwapFree: 959280 kB Dirty: 100 kB Writeback: 0 kB AnonPages: 294600 kB Mapped: 61736 kB Slab: 26508 kB SReclaimable: 17520 kB SUnreclaim: 8988 kB PageTables: 2868 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 1968772 kB Committed_AS: 504844 kB VmallocTotal: 122880 kB VmallocUsed: 18444 kB VmallocChunk: 103592 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 4096 kB DirectMap4k: 876536 kB DirectMap4M: 32768 kB
-2009-07-01T20:58:51Z INFO: writeSystemInfo: OS: Linux 2.6
-2009-07-01T20:58:51Z INFO: writeSystemInfo: OS info: Linux 2.6.29.3 #1 SMP Fri May 15 17:03:02 CEST 2009 i686
-2009-07-01T20:58:51Z INFO: writeDebugInfo: Opening debug file /home/aw/.imprudence/logs/debug_info.log
-2009-07-01T20:58:51Z INFO: init: J2C Engine is: OpenJPEG: 1.2.0, Runtime: 1.3.0
-2009-07-01T20:58:51Z INFO: init: libcurl version is: libcurl/7.16.4 OpenSSL/0.9.7c zlib/1.2.3.3 c-ares/1.4.0
-2009-07-01T20:58:51Z INFO: updateVectorize: Vectorization : DISABLED
-2009-07-01T20:58:51Z INFO: updateVectorize: Vector Processor : COMPILER DEFAULT
-2009-07-01T20:58:51Z INFO: updateVectorize: Vectorized Skinning : DISABLED
-2009-07-01T20:58:51Z WARNING: isFeatureAvailable: Feature RenderCubeMap not on feature list!
-2009-07-01T20:58:51Z INFO: grab_dbus_syms: Found DSO: libdbus-glib-1.so.2
-2009-07-01T20:58:51Z INFO: initCache: Headers: 139810 Textures size: 320 MB
-2009-07-01T20:58:51Z INFO: purgeTextures: TEXTURE CACHE: PURGED: 0 ENTRIES: 2650 CACHE SIZE: 65 MB
-2009-07-01T20:58:51Z INFO: initCache: VFS CACHE SIZE: 100 MB
-2009-07-01T20:58:51Z WARNING: LLVFS: Using index file /home/aw/.imprudence/cache/index.db2.x.1
-2009-07-01T20:58:51Z WARNING: LLVFS: Using data file /home/aw/.imprudence/cache/data.db2.x.1
-2009-07-01T20:58:51Z WARNING: LLVFS: Using index file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/static_index.db2
-2009-07-01T20:58:51Z WARNING: LLVFS: Using data file /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/static_data.db2
-2009-07-01T20:58:51Z INFO: initWindow: Initializing window...
-2009-07-01T20:58:51Z INFO: ll_try_gtk_init: Starting GTK Initialization.
-2009-07-01T20:58:51Z INFO: ll_try_gtk_init: GTK Initialized.
-2009-07-01T20:58:51Z INFO: ll_try_gtk_init: - Compiled against GTK version 2.4.14
-2009-07-01T20:58:51Z INFO: ll_try_gtk_init: - Running against GTK version 2.16.1
-2009-07-01T20:58:51Z INFO: createContext: createContext, fullscreen=0 size=1118x722
-2009-07-01T20:58:52Z INFO: createContext: Compiled against SDL 1.2.5
-2009-07-01T20:58:52Z INFO: createContext: Running against SDL 1.2.12
-2009-07-01T20:58:52Z INFO: createContext: createContext: creating window 1118x722x32
-2009-07-01T20:58:54Z INFO: x11_detect_VRAM_kb: Looking in /var/log/Xorg.0.log for VRAM info...
-2009-07-01T20:58:54Z INFO: createContext: GL buffer:
-2009-07-01T20:58:54Z INFO: createContext: Red Bits 8
-2009-07-01T20:58:54Z INFO: createContext: Green Bits 8
-2009-07-01T20:58:54Z INFO: createContext: Blue Bits 8
-2009-07-01T20:58:54Z INFO: createContext: Alpha Bits 8
-2009-07-01T20:58:54Z INFO: createContext: Depth Bits 24
-2009-07-01T20:58:54Z INFO: createContext: Stencil Bits 8
-2009-07-01T20:58:54Z INFO: initExtensions: Couldn't initialize GL_ARB_point_parameters
-2009-07-01T20:58:54Z INFO: initExtensions: Disabling mip-map generation for ATI GPUs (performance opt)
-2009-07-01T20:58:54Z WARNING: addFeature: LLFeatureList::Attempting to add preexisting feature Disregard128DefaultDrawDistance
-2009-07-01T20:58:54Z INFO: loadGPUClass: GPU is ATI Radeon Xpress
-2009-07-01T20:58:54Z INFO: applyBaseMasks: Setting GPU Class to Class0
-2009-07-01T20:58:54Z WARNING: LLViewerImageList::getMaxVideoRamSetting: VRAM amount not detected, defaulting to 128 MB
-2009-07-01T20:58:54Z WARNING: LLViewerImageList::getMaxVideoRamSetting: VRAM amount not detected, defaulting to 512 MB
-2009-07-01T20:58:54Z INFO: LLViewerImageList::updateMaxResidentTexMem: Total Video Memory set to: 128 MB
-2009-07-01T20:58:54Z INFO: LLViewerImageList::updateMaxResidentTexMem: Available Texture Memory set to: 96 MB
-2009-07-01T20:58:55Z INFO: restoreGL: Loading bumpmap: from viewerart
-2009-07-01T20:58:56Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
-2009-07-01T20:58:56Z INFO: setShaders:
-~~~~~~~~~~~~~~~~~~
- Loading Shaders:
-~~~~~~~~~~~~~~~~~~
-2009-07-01T20:58:56Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
-2009-07-01T20:58:57Z INFO: printGLInfoString: GL_VENDOR: ATI Technologies Inc.
-2009-07-01T20:58:57Z INFO: printGLInfoString: GL_RENDERER: ATI Radeon Xpress Series
-2009-07-01T20:58:57Z INFO: printGLInfoString: GL_VERSION: 2.1.8543 Release
-2009-07-01T20:58:57Z WARNING: init: ndof_init_first FAILED
-2009-07-01T20:58:57Z INFO: init: ndof: mDriverState=0; mNdofDev=0x9c2c1740; libinit=1
-2009-07-01T20:58:57Z INFO: LLTemplateParser: ### Message template version 2 ###
-2009-07-01T20:58:57Z INFO: start_net: startNet - receive buffer size : 262142
-2009-07-01T20:58:57Z INFO: start_net: startNet - send buffer size : 262142
-2009-07-01T20:58:57Z INFO: idle_startup: Message System Initialized.
-2009-07-01T20:58:57Z INFO: init: LLAudioEngine::init() AudioEngine successfully initialized
-2009-07-01T20:58:57Z INFO: init: LLAudioEngine_OpenAL::init() OpenAL successfully initialized
-2009-07-01T20:58:57Z INFO: init: OpenAL version: 1.1
-2009-07-01T20:58:57Z INFO: init: OpenAL vendor: OpenAL Community
-2009-07-01T20:58:57Z INFO: init: OpenAL renderer: OpenAL Soft
-2009-07-01T20:58:57Z INFO: init: ALUT version: 1.1
-2009-07-01T20:58:57Z INFO: init: ALC version: 1.1
-2009-07-01T20:58:57Z INFO: init: ALC default device: ALSA Software on default
-2009-07-01T20:58:57Z INFO: idle_startup: Audio Engine Initialized.
-2009-07-01T20:58:57Z INFO: setStartupState: Startup state changing from STATE_FIRST to (state #1)
-2009-07-01T20:58:59Z INFO: updateBrowserUserAgent: SecondLife/1.22.11.0 (Imprudence; default skin)
-2009-07-01T20:58:59Z INFO: setStartupState: Startup state changing from (state #1) to STATE_LOGIN_SHOW
-2009-07-01T20:58:59Z INFO: login_show: Initializing Login Screen
-2009-07-01T20:59:00Z INFO: setStartupState: Startup state changing from STATE_LOGIN_SHOW to STATE_LOGIN_WAIT
-2009-07-01T20:59:00Z WARNING: getChild: Found child named Say but of wrong type
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Say in chat_bar
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named end_call_btn in voice_remote
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy text named channel_label in voice_remote
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named voice_channel_bg in voice_remote
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named appearance_btn in toolbar
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named clothing_btn in toolbar
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named sit_btn in toolbar
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named History in chat_panel
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy combo_box named Gesture in chat_panel
-2009-07-01T20:59:00Z WARNING: getChild: Found child named Say but of wrong type
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Say in chat_panel
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy button named Chat in chat floater
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named bandwidth_tooltip in status
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named packet_loss_tooltip in status
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named friend_name_label in friends
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy view named friend_rights in friends
-2009-07-01T20:59:00Z WARNING: createDummyWidget: Making dummy text named process_rights_label in friends
-2009-07-01T20:59:01Z WARNING: createDummyWidget: Making dummy view named Shout in chat_bar
-2009-07-01T20:59:03Z INFO: setStartupState: Startup state changing from STATE_LOGIN_WAIT to STATE_LOGIN_CLEANUP
-2009-07-01T20:59:04Z INFO: idle_startup: Attempting login as: Armin Weatherwax
-2009-07-01T20:59:04Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml to load.
-2009-07-01T20:59:04Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml - No settings found.
-2009-07-01T20:59:04Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings.xml to load.
-2009-07-01T20:59:04Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings.xml - No settings found.
-2009-07-01T20:59:04Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/armin_weatherwax/settings_per_account.xml
-2009-07-01T20:59:04Z INFO: loadFile: Loading history.xml file at url_history.xml
-2009-07-01T20:59:04Z INFO: loadFile: file missing, ill-formed, or simply undefined; not changing the file
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_CLEANUP to STATE_LOGIN_AUTH_INIT
-2009-07-01T20:59:05Z INFO: rewriteURI: Rewriting http://127.0.0.1:9000/
-2009-07-01T20:59:05Z INFO: rewriteResult: [0] http://127.0.0.1:9000/
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTH_INIT to STATE_LOGIN_AUTHENTICATE
-2009-07-01T20:59:05Z INFO: authenticate: Authenticating: Armin Weatherwax,
-2009-07-01T20:59:05Z INFO: authenticate: Options: inventory-root, inventory-skeleton, inventory-lib-root, inventory-lib-owner, inventory-skel-lib, initial-outfit, gestures, event_categories, event_notifications, classified_categories, buddy-list, ui-config, tutorial_setting, login-flags, global-textures, END
-2009-07-01T20:59:05Z INFO: authenticate: LLUserAuth::authenticate: uri=http://127.0.0.1:9000/
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTHENTICATE to STATE_LOGIN_NO_DATA_YET
-2009-07-01T20:59:05Z INFO: transferRate: Buffer size: 105394 B
-2009-07-01T20:59:05Z INFO: transferRate: Transfer rate: 2041.61 Kb/s
-2009-07-01T20:59:05Z INFO: authResponse: Processed response: 0
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_DOWNLOADING to STATE_LOGIN_PROCESS_RESPONSE
-2009-07-01T20:59:05Z INFO: addCircuitData: LLCircuit::addCircuitData for 127.0.0.1:9000
-2009-07-01T20:59:05Z INFO: saveFile: Saved grids to /home/aw/.imprudence/user_settings/grid_info.xml
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_LOGIN_PROCESS_RESPONSE to STATE_WORLD_INIT
-2009-07-01T20:59:05Z INFO: LLVoiceClient::userAuthorized: name "Armin Weatherwax" , ID
-2009-07-01T20:59:05Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
-2009-07-01T20:59:05Z INFO: loadPresets: Loading Default WindLight settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Blue%20Midday.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D9AM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Sheer%20Surreality.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D12PM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Funky%20Funky%20Funky.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Fine%20Day.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D3PM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%203.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Funky%20Funky.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Night.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Coastal%20Sunset.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D9PM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Barcelona.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D6AM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Purple.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D6PM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Gelatto.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Incongruent%20Truths.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Fluffy%20Big%20Clouds.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%202.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Ghost.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Desert%20Sunset.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Default.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%204.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Blizzard.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Coastal%20Afternoon.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Foggy.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Sailor%27s%20Delight.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Pirate.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D3AM.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/Midday%201.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading WindLight sky setting from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/skies/A%2D12AM.xml
-2009-07-01T20:59:05Z INFO: loadPresets: Loading User WindLight settings from /home/aw/.imprudence/user_settings/windlight/skies/
-2009-07-01T20:59:05Z INFO: loadDayCycle: Loading DayCycle settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/days/Default.xml
-2009-07-01T20:59:05Z INFO: loadAllPresets: Loading Default water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Murky.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Pond.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Valdez.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Default.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Glassy.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/Second%20Plague.xml
-2009-07-01T20:59:05Z INFO: loadPreset: Loading water settings from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/water/SNAKE%21%21%21.xml
-2009-07-01T20:59:05Z INFO: loadAllPresets: Loading User water settings from /home/aw/.imprudence/user_settings/windlight/water/
-2009-07-01T20:59:05Z INFO: initVOClasses: Viewer Object size: 444
-2009-07-01T20:59:05Z INFO: addRegion: Adding new region (1000:1000)
-2009-07-01T20:59:05Z INFO: addRegion: Host: 127.0.0.1:9000
-2009-07-01T20:59:05Z INFO: idle_startup: Adding initial simulator { 256000, 256000, 0 }
-2009-07-01T20:59:05Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS//
-2009-07-01T20:59:05Z INFO: LLAgent::setRegion: Moving agent into region: located at 127.0.0.1:9000
-2009-07-01T20:59:05Z INFO: setStartupState: Startup state changing from STATE_WORLD_INIT to (state #12)
-2009-07-01T20:59:05Z INFO: LLVoiceClient::stateMachine: /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/bin/SLVoice not found.
-2009-07-01T20:59:06Z DEBUG: startup: Found GStreamer plugins:
-2009-07-01T20:59:06Z DEBUG: startup: private-slvideoplugin, loaded? Yes
-2009-07-01T20:59:06Z DEBUG: startup: wavparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpegdemux2, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: uridecodebin, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: esdsink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ogg, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ffmpeg, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: theora, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gnomevfs, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: asf, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: coreelements, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ossaudio, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: pulseaudio, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: coreindexers, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: typefindfunctions, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: autodetect, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: multifile, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: multipart, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: quicktime, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: id3demux, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ffmpegcolorspace, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: audioconvert, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: tcp, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: audioresample, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videoscale, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: avi, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: icydemux, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: vorbis, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: volume, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: playback, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: decodebin, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: alsa, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: udp, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: queue2, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dvdsub, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: musicbrainz, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: wildmidi, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: rfbsrc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dvdlpcmdec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ofa, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gstrtpmanager, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dfbvideosink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: fbdevsink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: siddec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpeg4videoparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpegvideoparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: nsfdec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: festival, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: alsaspdif, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpegtsparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: a52dec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: realmedia, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dvdread, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: flvdemux, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videosignal, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: sdp, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mms, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: spcdec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: speed, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: interleave, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: oss4, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dvb, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: h264parse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: bayer, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dc1394, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: vcdsrc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: tta, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: speexresample, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpeg2dec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gstinterlace, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: nuvdemux, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: faad, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ladspa, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mad, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: soundtouch, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: iec958, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cdxaparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: sndfile, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: filter, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: replaygain, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gsm, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cdaudio, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: metadata, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: freeze, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mve, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: jack, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpegaudioparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dtsdec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: selector, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dvdspu, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: real, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: musepack, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: neon, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: bz2, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: modplug, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: rawparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mythtv, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: vmnc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: stereo, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mpegstream, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: postproc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: subenc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: y4menc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: debug, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videobalance, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: alaw, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videomixer, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: annodex, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: png, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: goom, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: goom2k1, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: sdl, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: audiotestsrc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: level, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: matroska, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ximagesink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gdkpixbuf, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videorate, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: efence, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: mulaw, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: flac, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: spectrum, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: audiorate, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: xvimagesink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: auparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: shout2send, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: rtsp, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gio, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gdp, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: equalizer, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: wavenc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: wavpack, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videobox, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: smpte, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: alphacolor, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: adder, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: video4linux, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gamma, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: taglib, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cacasink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: jpeg, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: soup, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videocrop, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videotestsrc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: videoflip, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: speex, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cairo, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: monoscope, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: alpha, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: dv, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: subparse, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: aasink, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: halelements, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: audiofx, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: rtp, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cdparanoia, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: pango, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: apetag, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: ximagesrc, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: navigationtest, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cdio, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: video4linux2, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: 1394, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: flxdec, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: libvisual, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: cutter, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: gconfelements, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: effectv, loaded? No
-2009-07-01T20:59:06Z DEBUG: startup: staticelements, loaded? Yes
-2009-07-01T20:59:06Z INFO: setStartupState: Startup state changing from (state #12) to STATE_SEED_GRANTED_WAIT
-2009-07-01T20:59:06Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9000
-2009-07-01T20:59:06Z INFO: start: LLEventPollResponder::start <1> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:06Z INFO: setStartupState: Startup state changing from STATE_SEED_GRANTED_WAIT to STATE_SEED_CAP_GRANTED
-2009-07-01T20:59:06Z INFO: idle_startup: Initializing communications...
-2009-07-01T20:59:06Z INFO: importFile: LLCacheName loaded 72 agent names
-2009-07-01T20:59:06Z INFO: importFile: LLCacheName loaded 1 group names
-2009-07-01T20:59:06Z WARNING: createDummyWidget: Making dummy icon named voice_channel_icon in voice_remote
-2009-07-01T20:59:06Z INFO: LLDrawPoolWLSky: loading WindLight cloud noise from /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/app_settings/windlight/clouds2.tga
-2009-07-01T20:59:07Z WARNING: LLViewerImage::setIsMissingAsset: /home/aw/src/aaamyimprudence/linden/indra/viewer-linux-i686-relwithdebinfo/newview/packaged/skins/default/textures/ : Marking image as missing
-2009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_SEED_CAP_GRANTED to STATE_WORLD_WAIT
-2009-07-01T20:59:08Z INFO: idle_startup: viewer: UserLoginLocationReply() Enabling 127.0.0.1:9000 with code
-2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 243 going past packet end at 243
-2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 247 going past packet end at 243
-2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 251 going past packet end at 243
-2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 252 going past packet end at 243
-2009-07-01T20:59:08Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 253 going past packet end at 243
-2009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_WORLD_WAIT to STATE_AGENT_SEND
-2009-07-01T20:59:08Z INFO: setStartupState: Startup state changing from STATE_AGENT_SEND to STATE_AGENT_WAIT
-2009-07-01T20:59:08Z INFO: stopInternetStream: entered stopInternetStream()
-2009-07-01T20:59:09Z WARNING: process_agent_movement_complete: agent_movement_complete() with NULL avatarp.
-2009-07-01T20:59:09Z INFO: process_agent_movement_complete: Changing home region to 256000:256000
-2009-07-01T20:59:09Z INFO: sendToSim: Sending throttle settings, total BW 1050
-2009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_AGENT_WAIT to STATE_INVENTORY_SEND
-2009-07-01T20:59:09Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
-2009-07-01T20:59:09Z INFO: loadSkeleton: Successfully loaded 7 categories and 0 items from cache.
-2009-07-01T20:59:09Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
-2009-07-01T20:59:09Z INFO: loadSkeleton: Successfully loaded 5 categories and 0 items from cache.
-2009-07-01T20:59:09Z INFO: buildParentChildMap: LLInventoryModel::buildParentChildMap()
-2009-07-01T20:59:09Z INFO: idle_startup: Setting Inventory changed mask and notifying observers
-2009-07-01T20:59:09Z INFO: idle_startup: Registering Callbacks
-2009-07-01T20:59:09Z INFO: idle_startup: Inventory
-2009-07-01T20:59:09Z INFO: idle_startup: AvatarTracker
-2009-07-01T20:59:09Z INFO: idle_startup: Landmark
-2009-07-01T20:59:09Z INFO: idle_startup: Requesting Mute List
-2009-07-01T20:59:09Z INFO: idle_startup: Requesting Money Balance
-2009-07-01T20:59:09Z INFO: idle_startup: Requesting Agent Data
-2009-07-01T20:59:09Z INFO: idle_startup: Creating Inventory Views
-2009-07-01T20:59:09Z INFO: init: LLInventoryView::init: reading from 0xbfa919f0
-2009-07-01T20:59:09Z INFO: idle_startup: Inventory Views Created
-2009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_INVENTORY_SEND to STATE_MISC
-2009-07-01T20:59:09Z INFO: initWind: LLAudioEngine_OpenAL::initWind() start
-2009-07-01T20:59:09Z INFO: initWind: LLAudioEngine_OpenAL::initWind() done
-2009-07-01T20:59:09Z INFO: setStartupState: Startup state changing from STATE_MISC to STATE_PRECACHE
-2009-07-01T20:59:09Z INFO: idle: Transmitting sessions stats
-2009-07-01T20:59:09Z WARNING: send_stats: Could not get ViewerStats capability
-2009-07-01T20:59:09Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Ooh
-2009-07-01T20:59:09Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Aah
-2009-07-01T20:59:09Z WARNING: buildCharacter: Missing 'Ooh' morph for lipsync, using fallback.
-2009-07-01T20:59:09Z WARNING: buildCharacter: Missing 'Aah' morph for lipsync, using fallback.
-2009-07-01T20:59:09Z INFO: backgroundFetch: Inventory fetch completed
-2009-07-01T20:59:09Z INFO: addCircuitData: LLCircuit::addCircuitData for 127.0.0.1:9002
-2009-07-01T20:59:09Z INFO: addRegion: Adding new region (1000:1001)
-2009-07-01T20:59:09Z INFO: addRegion: Host: 127.0.0.1:9002
-2009-07-01T20:59:09Z INFO: process_enable_simulator: simulator_enable() Enabling 127.0.0.1:9002 with code
-2009-07-01T20:59:09Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS//
-2009-07-01T20:59:09Z INFO: processUseCachedMuteList: LLMuteList::processUseCachedMuteList()
-2009-07-01T20:59:09Z WARNING: loadFromFile: Couldn't open mute list /home/aw/.imprudence/cache/.cached_mute
-2009-07-01T20:59:09Z INFO: process_money_balance_reply: L$, credit, committed: 0 0 0
-2009-07-01T20:59:10Z INFO: LLAgent::sendAgentSetAppearance: TAT: Sent AgentSetAppearance: HEAD UPPER LOWER EYES
-2009-07-01T20:59:10Z INFO: LLAgent::sendAgentSetAppearance: TAT: Sending cached texture data
-2009-07-01T20:59:10Z INFO: deleteCachedImages: Clearing Static Textures KB GL:5120KB TGA:326KB
-2009-07-01T20:59:10Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9002
-2009-07-01T20:59:10Z INFO: start: LLEventPollResponder::start <2> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 4 bytes at position 243 going past packet end at 243
-2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 4 bytes at position 247 going past packet end at 243
-2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 251 going past packet end at 243
-2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 252 going past packet end at 243
-2009-07-01T20:59:10Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9002 trying to read 1 bytes at position 253 going past packet end at 243
-2009-07-01T20:59:14Z INFO: idle: Unknown object updates: 3
-2009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_PRECACHE to STATE_WEARABLES_WAIT
-2009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_WEARABLES_WAIT to STATE_CLEANUP
-2009-07-01T20:59:15Z INFO: setStartupState: Startup state changing from STATE_CLEANUP to STATE_STARTED
-2009-07-01T20:59:15Z INFO: idle_startup: Doing first audio_update_volume...
-2009-07-01T20:59:15Z INFO: idle_startup: Done first audio_update_volume.
-2009-07-01T20:59:15Z INFO: updateGeometry: WL Skydome strips in 3 batches.
-2009-07-01T20:59:20Z INFO: sendMapLayerRequest: LLWorldMap::sendMapLayerRequest via capability
-2009-07-01T20:59:20Z INFO: backgroundFetch: Inventory fetch completed
-2009-07-01T20:59:20Z INFO: parse: LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:OpenSim.Framework.Communications.Capabilities.LLSDMapLayerResponse
-2009-07-01T20:59:20Z INFO: result: LLMapLayerResponder::result from capabilities
-2009-07-01T20:59:26Z WARNING: onSelectServer: onSelectServer called
-2009-07-01T20:59:31Z WARNING: teleport: tp button current grid = local
-2009-07-01T20:59:31Z INFO: requestLogout: requestLogout
-2009-07-01T20:59:31Z WARNING: send_stats: Could not get ViewerStats capability
-2009-07-01T20:59:31Z INFO: sendLogoutRequest: Created logout marker file /home/aw/.imprudence/logs/Imprudence.logout_marker
-2009-07-01T20:59:31Z INFO: saveSnapshot: Saving snapshot to: /home/aw/.imprudence/armin_weatherwax/screen_last.bmp
-2009-07-01T20:59:32Z INFO: removeRegion: Removing region 256000:256256
-2009-07-01T20:59:32Z INFO: stop: LLEventPollResponder::stop <2> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:32Z INFO: disableCircuit: LLMessageSystem::disableCircuit for 127.0.0.1:9002
-2009-07-01T20:59:32Z WARNING: disableCircuit: Couldn't find circuit code for 127.0.0.1:9002
-2009-07-01T20:59:32Z INFO: stop: LLEventPollResponder::stop <2> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:38Z INFO: forceQuit: Destroying the entire world
-2009-07-01T20:59:38Z INFO: setStartupState: Startup state changing from STATE_STARTED to STATE_LOGIN_SHOW
-2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named ne_label in mini_mapview
-2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named nw_label in mini_mapview
-2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named sw_label in mini_mapview
-2009-07-01T20:59:38Z WARNING: createDummyWidget: Making dummy text named se_label in mini_mapview
-2009-07-01T20:59:38Z INFO: disconnectViewer: Disconnecting viewer!
-2009-07-01T20:59:38Z INFO: saveToFile: LLInventoryModel::saveToFile(/home/aw/.imprudence/cache/.inv)
-2009-07-01T20:59:38Z INFO: saveToFile: LLInventoryModel::saveToFile(/home/aw/.imprudence/cache/.inv)
-2009-07-01T20:59:38Z INFO: removeRegion: Removing region 256000:256000
-2009-07-01T20:59:38Z INFO: stop: LLEventPollResponder::stop <1> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:38Z INFO: cleanup: Viewer disconnected
-2009-07-01T20:59:38Z INFO: cleanup: Cleaning Up
-2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0xce9dc20 has 2 refs!
-2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x9534b040 has 2 refs!
-2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x95c48ed0 has 2 refs!
-2009-07-01T20:59:38Z INFO: LLAgent::setAvatarObject: Setting LLAgent::mAvatarObject to NULL
-2009-07-01T20:59:38Z WARNING: updateMeshTextures: updateMeshTextures: invalid host for object:
-2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x953a0100 has 2 refs!
-2009-07-01T20:59:38Z INFO: cleanupHUDObjects: LLHUDObject 0x95855210 has 2 refs!
-2009-07-01T20:59:38Z INFO: cleanup: HUD Objects cleaned up
-2009-07-01T20:59:38Z INFO: LLVoiceClient::stateMachine: Disabling voice before connection to daemon, terminating.
-2009-07-01T20:59:38Z INFO: setStartupState: Startup state changing from STATE_LOGIN_SHOW to STATE_LOGIN_CLEANUP
-2009-07-01T20:59:38Z INFO: idle_startup: Attempting login as: Armin Weatherwax
-2009-07-01T20:59:38Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml to load.
-2009-07-01T20:59:38Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings_crash_behavior.xml - No settings found.
-2009-07-01T20:59:38Z WARNING: loadFromFile: Cannot find file /home/aw/.imprudence/armin_weatherwax/settings.xml to load.
-2009-07-01T20:59:38Z WARNING: loadSettingsFromDirectory: Cannot load /home/aw/.imprudence/armin_weatherwax/settings.xml - No settings found.
-2009-07-01T20:59:38Z INFO: loadSettingsFromDirectory: Loaded settings file /home/aw/.imprudence/armin_weatherwax/settings_per_account.xml
-2009-07-01T20:59:38Z INFO: loadFile: Loading history.xml file at url_history.xml
-2009-07-01T20:59:38Z INFO: loadFile: file missing, ill-formed, or simply undefined; not changing the file
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_CLEANUP to STATE_LOGIN_AUTH_INIT
-2009-07-01T20:59:39Z INFO: rewriteURI: Rewriting http://127.0.0.1:9000/
-2009-07-01T20:59:39Z INFO: rewriteResult: [0] http://127.0.0.1:9000/
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTH_INIT to STATE_LOGIN_AUTHENTICATE
-2009-07-01T20:59:39Z INFO: authenticate: Authenticating: Armin Weatherwax,
-2009-07-01T20:59:39Z INFO: authenticate: Options: inventory-root, inventory-skeleton, inventory-lib-root, inventory-lib-owner, inventory-skel-lib, initial-outfit, gestures, event_categories, event_notifications, classified_categories, buddy-list, ui-config, tutorial_setting, login-flags, global-textures, END
-2009-07-01T20:59:39Z INFO: authenticate: LLUserAuth::authenticate: uri=http://127.0.0.1:9000/
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_AUTHENTICATE to STATE_LOGIN_NO_DATA_YET
-2009-07-01T20:59:39Z INFO: transferRate: Buffer size: 105394 B
-2009-07-01T20:59:39Z INFO: transferRate: Transfer rate: 5616.14 Kb/s
-2009-07-01T20:59:39Z INFO: authResponse: Processed response: 0
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_NO_DATA_YET to STATE_LOGIN_DOWNLOADING
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_DOWNLOADING to STATE_LOGIN_PROCESS_RESPONSE
-2009-07-01T20:59:39Z INFO: saveFile: Saved grids to /home/aw/.imprudence/user_settings/grid_info.xml
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_LOGIN_PROCESS_RESPONSE to STATE_WORLD_INIT
-2009-07-01T20:59:39Z INFO: LLVoiceClient::userAuthorized: name "Armin Weatherwax" , ID
-2009-07-01T20:59:39Z INFO: saveToFile: Saved to /home/aw/.imprudence/user_settings/settings_imprudence.xml
-2009-07-01T20:59:39Z INFO: addRegion: Adding new region (1000:1000)
-2009-07-01T20:59:39Z INFO: addRegion: Host: 127.0.0.1:9000
-2009-07-01T20:59:39Z INFO: idle_startup: Adding initial simulator { 256000, 256000, 0 }
-2009-07-01T20:59:39Z INFO: setSeedCapability: posting to seed http://127.0.0.1:9000/CAPS//
-2009-07-01T20:59:39Z INFO: LLAgent::setRegion: Moving agent into region: located at 127.0.0.1:9000
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_WORLD_INIT to (state #12)
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from (state #12) to STATE_SEED_GRANTED_WAIT
-2009-07-01T20:59:39Z INFO: LLEventPollResponder: LLEventPoll initialized with sender 127.0.0.1:9000
-2009-07-01T20:59:39Z INFO: start: LLEventPollResponder::start <3> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:39Z INFO: setStartupState: Startup state changing from STATE_SEED_GRANTED_WAIT to STATE_SEED_CAP_GRANTED
-2009-07-01T20:59:39Z INFO: idle_startup: Initializing communications...
-2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_SEED_CAP_GRANTED to STATE_WORLD_WAIT
-2009-07-01T20:59:42Z INFO: idle_startup: viewer: UserLoginLocationReply() Enabling 127.0.0.1:9000 with code
-2009-07-01T20:59:42Z INFO: stop: LLEventPollResponder::stop <1> http://127.0.0.1:9000/CAPS/EQG//
-2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_WORLD_WAIT to STATE_AGENT_SEND
-2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
-2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
-2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
-2009-07-01T20:59:42Z WARNING: sendEffects: Trying to send dead effect!
-2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_AGENT_SEND to STATE_AGENT_WAIT
-2009-07-01T20:59:42Z INFO: checkPacketInID: packet_out_of_order - got packet 370 expecting 1424 from 127.0.0.1:9000
-2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_AGENT_WAIT to STATE_INVENTORY_SEND
-2009-07-01T20:59:42Z INFO: stopInternetStream: entered stopInternetStream()
-2009-07-01T20:59:42Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
-2009-07-01T20:59:42Z INFO: loadSkeleton: Successfully loaded 7 categories and 0 items from cache.
-2009-07-01T20:59:42Z INFO: loadFromFile: LLInventoryModel::loadFromFile(/home/aw/.imprudence/cache/.inv)
-2009-07-01T20:59:42Z INFO: loadSkeleton: Successfully loaded 5 categories and 0 items from cache.
-2009-07-01T20:59:42Z INFO: buildParentChildMap: LLInventoryModel::buildParentChildMap()
-2009-07-01T20:59:42Z INFO: idle_startup: Setting Inventory changed mask and notifying observers
-2009-07-01T20:59:42Z INFO: idle_startup: Registering Callbacks
-2009-07-01T20:59:42Z INFO: idle_startup: Inventory
-2009-07-01T20:59:42Z INFO: idle_startup: AvatarTracker
-2009-07-01T20:59:42Z INFO: idle_startup: Landmark
-2009-07-01T20:59:42Z INFO: idle_startup: Requesting Mute List
-2009-07-01T20:59:42Z INFO: idle_startup: Requesting Money Balance
-2009-07-01T20:59:42Z INFO: idle_startup: Requesting Agent Data
-2009-07-01T20:59:42Z INFO: idle_startup: Creating Inventory Views
-2009-07-01T20:59:42Z INFO: init: LLInventoryView::init: reading from 0xbfa919f0
-2009-07-01T20:59:42Z INFO: idle_startup: Inventory Views Created
-2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_INVENTORY_SEND to STATE_MISC
-2009-07-01T20:59:42Z INFO: setStartupState: Startup state changing from STATE_MISC to STATE_PRECACHE
-2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 243 going past packet end at 243
-2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 4 bytes at position 247 going past packet end at 243
-2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 251 going past packet end at 243
-2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 252 going past packet end at 243
-2009-07-01T20:59:42Z WARNING: logRanOffEndOfPacket: Ran off end of packet RegionHandshake from 127.0.0.1:9000 trying to read 1 bytes at position 253 going past packet end at 243
-2009-07-01T20:59:42Z INFO: checkPacketInID: packet_out_of_order - got packet 3 expecting 371 from 127.0.0.1:9000
-2009-07-01T20:59:42Z WARNING: process_agent_movement_complete: agent_movement_complete() with NULL avatarp.
-2009-07-01T20:59:42Z INFO: process_agent_movement_complete: Changing home region to 256000:256000
-2009-07-01T20:59:42Z INFO: sendToSim: Sending throttle settings, total BW 1050
-2009-07-01T20:59:42Z INFO: backgroundFetch: Inventory fetch completed
-2009-07-01T20:59:42Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Ooh
-2009-07-01T20:59:42Z WARNING: getVisualParam: LLCharacter::getVisualParam() Invalid visual parameter: Lipsync_Aah
-2009-07-01T20:59:42Z WARNING: buildCharacter: Missing 'Ooh' morph for lipsync, using fallback.
-2009-07-01T20:59:42Z WARNING: buildCharacter: Missing 'Aah' morph for lipsync, using fallback.
-2009-07-01T20:59:42Z INFO: do_elfio_glibc_backtrace: Opening stack trace file /home/aw/.imprudence/logs/stack_trace.log
-2009-07-01T20:59:46Z INFO: do_elfio_glibc_backtrace: Finished generating stack trace.
-2009-07-01T20:59:46Z INFO: handleViewerCrash: Handle viewer crash entry.
-2009-07-01T20:59:46Z INFO: handleViewerCrash: Creating crash marker file /home/aw/.imprudence/logs/Imprudence.error_marker
-2009-07-01T20:59:46Z INFO: handleViewerCrash: Created crash marker file /home/aw/.imprudence/logs/Imprudence.error_marker
-2009-07-01T20:59:46Z INFO: handleViewerCrash: Handle viewer crash generating stats log.
-2009-07-01T20:59:46Z INFO: writeDebugInfo: Opening debug file /home/aw/.imprudence/logs/debug_info.log
diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp
index 5f0a875..e6ae7b5 100644
--- a/linden/indra/newview/llagent.cpp
+++ b/linden/indra/newview/llagent.cpp
@@ -466,6 +466,10 @@ void LLAgent::init()
//-----------------------------------------------------------------------------
void LLAgent::cleanup()
{
+ mInitialized = FALSE;
+ mWearablesLoaded = FALSE;
+ mShowAvatar = TRUE;
+
setSitCamera(LLUUID::null);
mAvatarObject = NULL;
mLookAt = NULL;
@@ -6592,11 +6596,19 @@ BOOL LLAgent::isWearingItem( const LLUUID& item_id )
// static
void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void** user_data )
{
+ if (gNoRender)
+ {
+ return;
+ }
+
// We should only receive this message a single time. Ignore subsequent AgentWearablesUpdates
// that may result from AgentWearablesRequest having been sent more than once.
+ // If we do this, then relogging won't work. - Gigs
+ /*
static bool first = true;
if (!first) return;
first = false;
+ */
LLUUID agent_id;
gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp
index 60faaf2..128f33a 100644
--- a/linden/indra/newview/llappviewer.cpp
+++ b/linden/indra/newview/llappviewer.cpp
@@ -3797,7 +3797,7 @@ void LLAppViewer::disconnectViewer()
LLWorld::getInstance()->destroyClass();
if (mQuitRequested)
- cleanup_xfer_manager();
+ cleanup_xfer_manager();
}
void LLAppViewer::forceErrorLLError()
diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp
index 1029a3c..93eb7ac 100644
--- a/linden/indra/newview/llinventorymodel.cpp
+++ b/linden/indra/newview/llinventorymodel.cpp
@@ -1499,7 +1499,7 @@ void LLInventoryModel::stopBackgroundFetch()
//static
void LLInventoryModel::backgroundFetch(void*)
{
- if (sBackgroundFetchActive && gAgent.getRegion())
+ if (sBackgroundFetchActive)
{
//If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
diff --git a/linden/indra/newview/llinventorymodel.h b/linden/indra/newview/llinventorymodel.h
index 7c7d231..e95d246 100644
--- a/linden/indra/newview/llinventorymodel.h
+++ b/linden/indra/newview/llinventorymodel.h
@@ -323,6 +323,8 @@ public:
// relations.
void buildParentChildMap();
+ // Empty the entire contents
+ void empty();
//
// Category accounting.
//
@@ -374,6 +376,7 @@ public:
static bool isEverythingFetched();
static void backgroundFetch(void*); // background fetch idle function
static void incrBulkFetch(S16 fetching) { sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; }
+
protected:
// Internal methods which add inventory and make sure that all of
@@ -387,8 +390,7 @@ protected:
// preferred type. Returns LLUUID::null if not found
LLUUID findCatUUID(LLAssetType::EType preferred_type);
- // Empty the entire contents
- void empty();
+
// Given the current state of the inventory items, figure out the
// clone information. *FIX: This is sub-optimal, since we can
diff --git a/linden/indra/newview/llinventoryview.cpp b/linden/indra/newview/llinventoryview.cpp
index 0f1eb2b..d79c6e9 100644
--- a/linden/indra/newview/llinventoryview.cpp
+++ b/linden/indra/newview/llinventoryview.cpp
@@ -941,6 +941,7 @@ void LLInventoryView::cleanup()
{
sActiveViews.get(i)->destroy();
}
+ gInventory.empty();
}
void LLInventoryView::toggleFindOptions()
diff --git a/linden/indra/newview/llviewerjointattachment.h b/linden/indra/newview/llviewerjointattachment.h
index dd63bfd..cbfee0b 100644
--- a/linden/indra/newview/llviewerjointattachment.h
+++ b/linden/indra/newview/llviewerjointattachment.h
@@ -98,7 +98,9 @@ protected:
void calcLOD();
protected:
- LLPointer mAttachedObject;
+
+ // Backlink only; don't make this an LLPointer.
+ LLViewerObject* mAttachedObject;
BOOL mVisibleInFirst;
LLVector3 mOriginalPos;
S32 mGroup;
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp
index 2940bdd..f75ca7d 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -564,6 +564,11 @@ void set_underclothes_menu_options()
void init_menus()
{
+ if (gMenuHolder)
+ {
+ cleanup_menus();
+ }
+
S32 top = gViewerWindow->getRootView()->getRect().getHeight();
S32 width = gViewerWindow->getRootView()->getRect().getWidth();
diff --git a/mAttachedObject.diff.txt b/mAttachedObject.diff.txt
deleted file mode 100644
index 73ffab5..0000000
--- a/mAttachedObject.diff.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/linden/indra/newview/llviewerjointattachment.h b/linden/indra/newview/llviewerjointattachment.h
-index dd63bfd..6a505c0 100644
---- a/linden/indra/newview/llviewerjointattachment.h
-+++ b/linden/indra/newview/llviewerjointattachment.h
-@@ -98,7 +98,9 @@ protected:
- void calcLOD();
-
- protected:
-- LLPointer mAttachedObject;
-+
-+ // Backlink only; don't make this an LLPointer.
-+ LLViewerObject* mAttachedObject;
- BOOL mVisibleInFirst;
- LLVector3 mOriginalPos;
- S32 mGroup;
-
diff --git a/meerkat-llmenugl.diff.txt b/meerkat-llmenugl.diff.txt
deleted file mode 100644
index 7ca8c2c..0000000
--- a/meerkat-llmenugl.diff.txt
+++ /dev/null
@@ -1,534 +0,0 @@
-diff -uwN /linden/indra/llui/llmenugl.cpp /linden/indra/llui/llmenugl.cpp
---- /linden/indra/llui/llmenugl.cpp 2009-06-12 14:14:40.000000000 +0200
-+++ /linden/indra/llui/llmenugl.cpp 2009-06-23 02:16:35.000000000 +0200
-@@ -413,7 +413,7 @@
- LLMenuGL::setKeyboardMode(FALSE);
-
- doIt();
-- make_ui_sound("UISndClickRelease");
-+ //make_ui_sound("UISndClickRelease");
- return TRUE;
- }
-
-@@ -1033,47 +1033,30 @@
- }
-
-
--LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch,
-+LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch,
- KEY key, MASK mask ) :
- LLMenuItemGL( name, label, key, mask ),
- mBranch( branch )
- {
-- if(!dynamic_cast(branch.get()))
-- {
-- llerrs << "Non-menu handle passed as branch reference." << llendl;
-- }
--
-- if(getBranch())
-- {
-- getBranch()->setVisible( FALSE );
-- getBranch()->setParentMenuItem(this);
-- }
--}
--
--LLMenuItemBranchGL::~LLMenuItemBranchGL()
--{
-- LLView::deleteViewByHandle(mBranch);
-+ mBranch->setVisible( FALSE );
-+ mBranch->setParentMenuItem(this);
- }
-
- // virtual
- LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const
- {
- // richard: this is redundant with parent, remove
-- if (getBranch())
-+ if (mBranch->getName() == name)
- {
-- if(getBranch()->getName() == name)
-- {
-- return getBranch();
-+ return mBranch;
- }
--
- // Always recurse on branches
-- LLView* child = getBranch()->getChildView(name, recurse, FALSE);
-- if(child)
-+ LLView* child = mBranch->getChildView(name, recurse, FALSE);
-+ if (!child)
- {
-- return child;
-+ child = LLView::getChildView(name, recurse, create_if_missing);
- }
-- }
-- return LLView::getChildView(name, recurse, create_if_missing);;
-+ return child;
- }
-
- // virtual
-@@ -1083,25 +1066,21 @@
- LLMenuGL::setKeyboardMode(FALSE);
-
- doIt();
-- make_ui_sound("UISndClickRelease");
-+ //make_ui_sound("UISndClickRelease");
- return TRUE;
- }
-
- BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
- {
-- if(getBranch())
-- {
-- return getBranch()->handleAcceleratorKey(key, mask);
-- }
-- return FALSE;
-+ return mBranch->handleAcceleratorKey(key, mask);
- }
-
- // virtual
- LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const
- {
-- if (getBranch())
-+ if (mBranch)
- {
-- return getBranch()->getXML();
-+ return mBranch->getXML();
- }
-
- return LLMenuItemGL::getXML();
-@@ -1112,19 +1091,16 @@
- // if not, it will be added to the list
- BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list *listp)
- {
-- if(getBranch())
-- {
-- U32 item_count = getBranch()->getItemCount();
-+ U32 item_count = mBranch->getItemCount();
- LLMenuItemGL *item;
-
- while (item_count--)
- {
-- if ((item = getBranch()->getItem(item_count)))
-+ if ((item = mBranch->getItem(item_count)))
- {
- return item->addToAcceleratorList(listp);
- }
- }
-- }
- return FALSE;
- }
-
-@@ -1146,18 +1122,18 @@
-
- // keyboard navigation automatically propagates highlight to sub-menu
- // to facilitate fast menu control via jump keys
-- if (getBranch() && LLMenuGL::getKeyboardMode() && !getBranch()->getHighlightedItem())
-+ if (LLMenuGL::getKeyboardMode() && !mBranch->getHighlightedItem())
- {
-- getBranch()->highlightNextItem(NULL);
-+ mBranch->highlightNextItem(NULL);
- }
- }
-
- BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
- {
- BOOL handled = FALSE;
-- if (called_from_parent && getBranch())
-+ if (called_from_parent)
- {
-- handled = getBranch()->handleKey(key, mask, called_from_parent);
-+ handled = mBranch->handleKey(key, mask, called_from_parent);
- }
-
- if (!handled)
-@@ -1171,9 +1147,9 @@
- BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
- {
- BOOL handled = FALSE;
-- if (called_from_parent && getBranch())
-+ if (called_from_parent)
- {
-- handled = getBranch()->handleUnicodeChar(uni_char, TRUE);
-+ handled = mBranch->handleUnicodeChar(uni_char, TRUE);
- }
-
- if (!handled)
-@@ -1189,19 +1165,14 @@
- {
- if (highlight == getHighlight()) return;
-
-- if(!getBranch())
-- {
-- return;
-- }
--
-- BOOL auto_open = getEnabled() && (!getBranch()->getVisible() || getBranch()->getTornOff());
-+ BOOL auto_open = getEnabled() && (!mBranch->getVisible() || mBranch->getTornOff());
- // torn off menus don't open sub menus on hover unless they have focus
- if (getMenu()->getTornOff() && !((LLFloater*)getMenu()->getParent())->hasFocus())
- {
- auto_open = FALSE;
- }
- // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus)
-- if (getBranch()->getTornOff())
-+ if (mBranch->getTornOff())
- {
- auto_open = FALSE;
- }
-@@ -1215,14 +1186,14 @@
- }
- else
- {
-- if (getBranch()->getTornOff())
-+ if (mBranch->getTornOff())
- {
-- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
-- getBranch()->clearHoverItem();
-+ ((LLFloater*)mBranch->getParent())->setFocus(FALSE);
-+ mBranch->clearHoverItem();
- }
- else
- {
-- getBranch()->setVisible( FALSE );
-+ mBranch->setVisible( FALSE );
- }
- }
- }
-@@ -1230,7 +1201,7 @@
- void LLMenuItemBranchGL::draw()
- {
- LLMenuItemGL::draw();
-- if (getBranch() && getBranch()->getVisible() && !getBranch()->getTornOff())
-+ if (mBranch->getVisible() && !mBranch->getTornOff())
- {
- setHighlight(TRUE);
- }
-@@ -1238,33 +1209,33 @@
-
- void LLMenuItemBranchGL::updateBranchParent(LLView* parentp)
- {
-- if (getBranch() && getBranch()->getParent() == NULL)
-+ if (mBranch->getParent() == NULL)
- {
- // make the branch menu a sibling of my parent menu
-- getBranch()->updateParent(parentp);
-+ mBranch->updateParent(parentp);
- }
- }
-
- void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility )
- {
-- if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff())
-+ if (new_visibility == FALSE && !mBranch->getTornOff())
- {
-- getBranch()->setVisible(FALSE);
-+ mBranch->setVisible(FALSE);
- }
- LLMenuItemGL::onVisibilityChange(new_visibility);
- }
-
- BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask )
- {
-- if (getMenu()->getVisible() && getBranch() && getBranch()->getVisible() && key == KEY_LEFT)
-+ if (getMenu()->getVisible() && mBranch->getVisible() && key == KEY_LEFT)
- {
- // switch to keyboard navigation mode
- LLMenuGL::setKeyboardMode(TRUE);
-
-- BOOL handled = getBranch()->clearHoverItem();
-- if (getBranch()->getTornOff())
-+ BOOL handled = mBranch->clearHoverItem();
-+ if (mBranch->getTornOff())
- {
-- ((LLFloater*)getBranch()->getParent())->setFocus(FALSE);
-+ ((LLFloater*)mBranch->getParent())->setFocus(FALSE);
- }
- if (handled && getMenu()->getTornOff())
- {
-@@ -1275,12 +1246,12 @@
-
- if (getHighlight() &&
- getMenu()->isOpen() &&
-- key == KEY_RIGHT && getBranch() && !getBranch()->getHighlightedItem())
-+ key == KEY_RIGHT && !mBranch->getHighlightedItem())
- {
- // switch to keyboard navigation mode
- LLMenuGL::setKeyboardMode(TRUE);
-
-- LLMenuItemGL* itemp = getBranch()->highlightNextItem(NULL);
-+ LLMenuItemGL* itemp = mBranch->highlightNextItem(NULL);
- if (itemp)
- {
- return TRUE;
-@@ -1292,39 +1263,37 @@
-
- void LLMenuItemBranchGL::openMenu()
- {
-- if(!getBranch()) return;
--
-- if (getBranch()->getTornOff())
-+ if (mBranch->getTornOff())
- {
-- gFloaterView->bringToFront((LLFloater*)getBranch()->getParent());
-+ gFloaterView->bringToFront((LLFloater*)mBranch->getParent());
- // this might not be necessary, as torn off branches don't get focus and hence no highligth
-- getBranch()->highlightNextItem(NULL);
-+ mBranch->highlightNextItem(NULL);
- }
-- else if( !getBranch()->getVisible() )
-+ else if( !mBranch->getVisible() )
- {
- // get valid rectangle for menus
- const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect();
-
-- getBranch()->arrange();
-+ mBranch->arrange();
-
-- LLRect rect = getBranch()->getRect();
-+ LLRect rect = mBranch->getRect();
- // calculate root-view relative position for branch menu
- S32 left = getRect().mRight;
- S32 top = getRect().mTop - getRect().mBottom;
-
-- localPointToOtherView(left, top, &left, &top, getBranch()->getParent());
-+ localPointToOtherView(left, top, &left, &top, mBranch->getParent());
-
- rect.setLeftTopAndSize( left, top,
- rect.getWidth(), rect.getHeight() );
-
-- if (getBranch()->getCanTearOff())
-+ if (mBranch->getCanTearOff())
- {
- rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS);
- }
-- getBranch()->setRect( rect );
-+ mBranch->setRect( rect );
- S32 x = 0;
- S32 y = 0;
-- getBranch()->localPointToOtherView( 0, 0, &x, &y, getBranch()->getParent() );
-+ mBranch->localPointToOtherView( 0, 0, &x, &y, mBranch->getParent() );
- S32 delta_x = 0;
- S32 delta_y = 0;
- if( y < menu_region_rect.mBottom )
-@@ -1338,9 +1307,8 @@
- // move sub-menu over to left side
- delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth())));
- }
-- getBranch()->translate( delta_x, delta_y );
-- getBranch()->setVisible( TRUE );
-- getBranch()->getParent()->sendChildToFront(getBranch());
-+ mBranch->translate( delta_x, delta_y );
-+ mBranch->setVisible( TRUE );
- }
- }
-
-@@ -1357,7 +1325,7 @@
- protected:
-
- public:
-- LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLHandle branch,
-+ LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLMenuGL* branch,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
-
- virtual std::string getType() const { return "menu"; }
-@@ -1390,7 +1358,7 @@
-
- LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const std::string& name,
- const std::string& label,
-- LLHandle branch,
-+ LLMenuGL* branch,
- KEY key, MASK mask ) :
- LLMenuItemBranchGL( name, label, branch, key, mask )
- {
-@@ -1459,7 +1427,6 @@
-
- setHighlight(TRUE);
- branch->setVisible( TRUE );
-- branch->getParent()->sendChildToFront(branch);
- }
- }
- }
-@@ -2288,7 +2255,7 @@
- mSpilloverMenu->setBackgroundColor( mBackgroundColor );
- mSpilloverMenu->setCanTearOff(FALSE);
-
-- mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu->getHandle());
-+ mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu);
- mSpilloverBranch->setFontStyle(LLFontGL::ITALIC);
- }
- }
-@@ -2308,6 +2275,9 @@
- mItems.erase(found_iter);
- }
-
-+ delete mSpilloverBranch;
-+ mSpilloverBranch = NULL;
-+
- // pop off spillover items
- while (mSpilloverMenu->getItemCount())
- {
-@@ -2318,12 +2288,6 @@
- mItems.push_back(itemp);
- addChild(itemp);
- }
--
-- // Delete the branch, and since the branch will delete the menu,
-- // set the menu* to null.
-- delete mSpilloverBranch;
-- mSpilloverBranch = NULL;
-- mSpilloverMenu = NULL;
- }
- }
-
-@@ -2496,7 +2460,7 @@
- BOOL success = TRUE;
-
- LLMenuItemBranchGL* branch = NULL;
-- branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu->getHandle() );
-+ branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu );
- branch->setJumpKey(menu->getJumpKey());
- success &= append( branch );
-
-@@ -2994,7 +2958,6 @@
- }
- menu->translate( delta_x, delta_y );
- menu->setVisible( TRUE );
-- menu->getParent()->sendChildToFront(menu);
- }
-
- //-----------------------------------------------------------------------------
-@@ -3185,31 +3148,31 @@
- switch(pieItemIndexFromXY(x, y))
- {
- case 0:
-- make_ui_sound("UISndPieMenuSliceHighlight0");
-+ //make_ui_sound("UISndPieMenuSliceHighlight0");
- break;
- case 1:
-- make_ui_sound("UISndPieMenuSliceHighlight1");
-+ //make_ui_sound("UISndPieMenuSliceHighlight1");
- break;
- case 2:
-- make_ui_sound("UISndPieMenuSliceHighlight2");
-+ //make_ui_sound("UISndPieMenuSliceHighlight2");
- break;
- case 3:
-- make_ui_sound("UISndPieMenuSliceHighlight3");
-+ //make_ui_sound("UISndPieMenuSliceHighlight3");
- break;
- case 4:
-- make_ui_sound("UISndPieMenuSliceHighlight4");
-+ //make_ui_sound("UISndPieMenuSliceHighlight4");
- break;
- case 5:
-- make_ui_sound("UISndPieMenuSliceHighlight5");
-+ //make_ui_sound("UISndPieMenuSliceHighlight5");
- break;
- case 6:
-- make_ui_sound("UISndPieMenuSliceHighlight6");
-+ //make_ui_sound("UISndPieMenuSliceHighlight6");
- break;
- case 7:
-- make_ui_sound("UISndPieMenuSliceHighlight7");
-+ //make_ui_sound("UISndPieMenuSliceHighlight7");
- break;
- default:
-- make_ui_sound("UISndPieMenuSliceHighlight0");
-+ //make_ui_sound("UISndPieMenuSliceHighlight0");
- break;
- }
- }
-@@ -3357,7 +3320,7 @@
-
- if (mFirstMouseDown)
- {
-- make_ui_sound("UISndPieMenuAppear");
-+ //make_ui_sound("UISndPieMenuAppear");
- mFirstMouseDown = FALSE;
- }
-
-@@ -3730,7 +3693,7 @@
-
- if (!mFirstMouseDown)
- {
-- make_ui_sound("UISndPieMenuAppear");
-+ //make_ui_sound("UISndPieMenuAppear");
- }
-
- LLView::setVisible(TRUE);
-@@ -3759,7 +3722,7 @@
- mHoverItem = NULL;
- }
-
-- make_ui_sound("UISndPieMenuHide");
-+ //make_ui_sound("UISndPieMenuHide");
-
- mFirstMouseDown = FALSE;
- mRightMouseDown = FALSE;
-@@ -4105,7 +4068,7 @@
- BOOL success = TRUE;
-
- LLMenuItemBranchGL* branch = NULL;
-- branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu->getHandle());
-+ branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu );
- success &= branch->addToAcceleratorList(&mAccelerators);
- success &= append( branch );
- branch->setJumpKey(branch->getJumpKey());
-diff -uwN /linden/indra/llui/llmenugl.h /linden/indra/llui/llmenugl.h
---- /linden/indra/llui/llmenugl.h 2009-06-12 14:14:40.000000000 +0200
-+++ /linden/indra/llui/llmenugl.h 2009-06-23 02:16:35.000000000 +0200
-@@ -89,7 +89,6 @@
- static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }
-
- LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE );
-- virtual ~LLMenuItemGL() {};
-
- virtual void setValue(const LLSD& value) { setLabel(value.asString()); }
-
-@@ -562,11 +561,8 @@
- class LLMenuItemBranchGL : public LLMenuItemGL
- {
- public:
-- LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch,
-+ LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch,
- KEY key = KEY_NONE, MASK mask = MASK_NONE );
--
-- virtual ~LLMenuItemBranchGL();
--
- virtual LLXMLNodePtr getXML(bool save_children = true) const;
-
- virtual std::string getType() const { return "menu"; }
-@@ -593,11 +589,11 @@
-
- virtual BOOL handleKeyHere(KEY key, MASK mask);
-
-- virtual BOOL isActive() const { return isOpen() && getBranch()->getHighlightedItem(); }
-+ virtual BOOL isActive() const { return isOpen() && mBranch->getHighlightedItem(); }
-
-- virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); }
-+ virtual BOOL isOpen() const { return mBranch->isOpen(); }
-
-- LLMenuGL *getBranch() const { return (LLMenuGL*)(mBranch.get()); }
-+ LLMenuGL *getBranch() const { return mBranch; }
-
- virtual void updateBranchParent( LLView* parentp );
-
-@@ -606,14 +602,14 @@
-
- virtual void draw();
-
-- virtual void setEnabledSubMenus(BOOL enabled) { if(getBranch()) getBranch()->setEnabledSubMenus(enabled); }
-+ virtual void setEnabledSubMenus(BOOL enabled) { mBranch->setEnabledSubMenus(enabled); }
-
- virtual void openMenu();
-
- virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
-
- private:
-- LLHandle mBranch;
-+ LLMenuGL* mBranch;
- }; // end class LLMenuItemBranchGL
-
-
-
diff --git a/meerkat-message.diff.txt b/meerkat-message.diff.txt
deleted file mode 100644
index a0e3ffc..0000000
--- a/meerkat-message.diff.txt
+++ /dev/null
@@ -1,1319 +0,0 @@
-diff --git a/linden/indra/llcommon/llstat.cpp b/linden/indra/llcommon/llstat.cpp
-index 31a72e2..74e8bf1 100644
---- a/linden/indra/llcommon/llstat.cpp
-+++ b/linden/indra/llcommon/llstat.cpp
-@@ -31,288 +31,17 @@
- #include "linden_common.h"
-
- #include "llstat.h"
--#include "lllivefile.h"
--#include "llerrorcontrol.h"
- #include "llframetimer.h"
- #include "timing.h"
--#include "llsd.h"
--#include "llsdserialize.h"
--#include "llstl.h"
--#include "u64.h"
-
-
--// statics
--BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information
--LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
--std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
-
--//------------------------------------------------------------------------
--// Live config file to trigger stats logging
--static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd";
--static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds
--
--class LLStatsConfigFile : public LLLiveFile
--{
--public:
-- LLStatsConfigFile()
-- : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE),
-- mChanged(false), mStatsp(NULL) { }
--
-- static std::string filename();
--
--protected:
-- /* virtual */ void loadFile();
--
--public:
-- void init(LLPerfStats* statsp);
-- static LLStatsConfigFile& instance();
-- // return the singleton stats config file
--
-- bool mChanged;
--
--protected:
-- LLPerfStats* mStatsp;
--};
--
--std::string LLStatsConfigFile::filename()
--{
-- return STATS_CONFIG_FILE_NAME;
--}
--
--void LLStatsConfigFile::init(LLPerfStats* statsp)
--{
-- mStatsp = statsp;
--}
--
--LLStatsConfigFile& LLStatsConfigFile::instance()
--{
-- static LLStatsConfigFile the_file;
-- return the_file;
--}
--
--
--/* virtual */
--// Load and parse the stats configuration file
--void LLStatsConfigFile::loadFile()
--{
-- if (!mStatsp)
-- {
-- llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl;
-- return;
-- }
-- mChanged = true;
--
-- LLSD stats_config;
-- {
-- llifstream file(filename().c_str());
-- if (file.is_open())
-- {
-- LLSDSerialize::fromXML(stats_config, file);
-- if (stats_config.isUndefined())
-- {
-- llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl;
-- mStatsp->setReportPerformanceDuration( 0.f );
-- return;
-- }
-- }
-- else
-- { // File went away, turn off stats if it was on
-- if ( mStatsp->frameStatsIsRunning() )
-- {
-- llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl;
-- mStatsp->setReportPerformanceDuration( 0.f );
-- }
-- return;
-- }
-- }
--
-- F32 duration = 0.f;
-- F32 interval = 0.f;
--
-- const char * w = "duration";
-- if (stats_config.has(w))
-- {
-- duration = (F32)stats_config[w].asReal();
-- }
-- w = "interval";
-- if (stats_config.has(w))
-- {
-- interval = (F32)stats_config[w].asReal();
-- }
--
-- mStatsp->setReportPerformanceDuration( duration );
-- mStatsp->setReportPerformanceInterval( interval );
--
-- if ( duration > 0 )
-- {
-- if ( interval == 0.f )
-- {
-- llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl;
-- }
-- else
-- {
-- llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl;
-- }
-- }
-- else
-- {
-- llinfos << "Performance stats recording turned off" << llendl;
-- }
--}
--
--
--//------------------------------------------------------------------------
--
--LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) :
-- mFrameStatsFileFailure(FALSE),
-- mSkipFirstFrameStats(FALSE),
-- mProcessName(process_name),
-- mProcessPID(process_pid),
-- mReportPerformanceStatInterval(1.f),
-- mReportPerformanceStatEnd(0.0)
--{ }
--
--LLPerfStats::~LLPerfStats()
--{
-- LLPerfBlock::clearDynamicStats();
-- mFrameStatsFile.close();
--}
--
--void LLPerfStats::init()
--{
-- // Initialize the stats config file instance.
-- (void) LLStatsConfigFile::instance().init(this);
-- (void) LLStatsConfigFile::instance().checkAndReload();
--}
--
--// Open file for statistics
--void LLPerfStats::openPerfStatsFile()
--{
-- if ( !mFrameStatsFile
-- && !mFrameStatsFileFailure )
-- {
-- std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID);
-- mFrameStatsFile.close();
-- mFrameStatsFile.clear();
-- mFrameStatsFile.open(stats_file, llofstream::out);
-- if ( mFrameStatsFile.fail() )
-- {
-- llinfos << "Error opening statistics log file " << stats_file << llendl;
-- mFrameStatsFileFailure = TRUE;
-- }
-- else
-- {
-- LLSD process_info = LLSD::emptyMap();
-- process_info["name"] = mProcessName;
-- process_info["pid"] = (LLSD::Integer) mProcessPID;
-- process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval;
-- // Add process-specific info.
-- addProcessHeaderInfo(process_info);
--
-- mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl;
-- }
-- }
--}
--
--// Dump out performance metrics over some time interval
--void LLPerfStats::dumpIntervalPerformanceStats()
--{
-- // Ensure output file is OK
-- openPerfStatsFile();
--
-- if ( mFrameStatsFile )
-- {
-- LLSD stats = LLSD::emptyMap();
--
-- LLStatAccum::TimeScale scale;
-- if ( getReportPerformanceInterval() == 0.f )
-- {
-- scale = LLStatAccum::SCALE_PER_FRAME;
-- }
-- else if ( getReportPerformanceInterval() < 0.5f )
-- {
-- scale = LLStatAccum::SCALE_100MS;
-- }
-- else
-- {
-- scale = LLStatAccum::SCALE_SECOND;
-- }
--
-- // Write LLSD into log
-- stats["utc_time"] = (LLSD::String) LLError::utcTime();
-- stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch
-- stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount();
--
-- // Add process-specific frame info.
-- addProcessFrameInfo(stats, scale);
-- LLPerfBlock::addStatsToLLSDandReset( stats, scale );
--
-- mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl;
-- }
--}
--
--// Set length of performance stat recording
--void LLPerfStats::setReportPerformanceDuration( F32 seconds )
--{
-- if ( seconds <= 0.f )
-- {
-- mReportPerformanceStatEnd = 0.0;
-- LLPerfBlock::setStatsEnabled( FALSE );
-- mFrameStatsFile.close();
-- LLPerfBlock::clearDynamicStats();
-- }
-- else
-- {
-- mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
-- // Clear failure flag to try and create the log file once
-- mFrameStatsFileFailure = FALSE;
-- LLPerfBlock::setStatsEnabled( TRUE );
-- mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
-- }
--}
--
--void LLPerfStats::updatePerFrameStats()
--{
-- (void) LLStatsConfigFile::instance().checkAndReload();
-- static LLFrameTimer performance_stats_timer;
-- if ( frameStatsIsRunning() )
-- {
-- if ( mReportPerformanceStatInterval == 0 )
-- { // Record info every frame
-- if ( mSkipFirstFrameStats )
-- { // Skip the first time - was started this frame
-- mSkipFirstFrameStats = FALSE;
-- }
-- else
-- {
-- dumpIntervalPerformanceStats();
-- }
-- }
-- else
-- {
-- performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() );
-- if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval ))
-- {
-- dumpIntervalPerformanceStats();
-- }
-- }
--
-- if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd )
-- { // Reached end of time, clear it to stop reporting
-- setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly
-- llinfos << "Recording performance stats completed" << llendl;
-- }
-- }
--}
--
--
--//------------------------------------------------------------------------
--
--U64 LLStatAccum::sScaleTimes[NUM_SCALES] =
-+U64 LLStatAccum::sScaleTimes[IMPL_NUM_SCALES] =
- {
- USEC_PER_SEC / 10, // 100 millisec
- USEC_PER_SEC * 1, // seconds
- USEC_PER_SEC * 60, // minutes
-+ USEC_PER_SEC * 60 * 2 // two minutes
- #if ENABLE_LONG_TIME_STATS
- // enable these when more time scales are desired
- USEC_PER_SEC * 60*60, // hours
-@@ -342,7 +71,7 @@ void LLStatAccum::reset(U64 when)
- mRunning = TRUE;
- mLastTime = when;
-
-- for (int i = 0; i < NUM_SCALES; ++i)
-+ for (int i = 0; i < IMPL_NUM_SCALES; ++i)
- {
- mBuckets[i].accum = 0.0;
- mBuckets[i].endTime = when + sScaleTimes[i];
-@@ -375,7 +104,7 @@ void LLStatAccum::sum(F64 value, U64 when)
- // how long is this value for
- U64 timeSpan = when - mLastTime;
-
-- for (int i = 0; i < NUM_SCALES; ++i)
-+ for (int i = 0; i < IMPL_NUM_SCALES; ++i)
- {
- Bucket& bucket = mBuckets[i];
-
-@@ -421,12 +150,7 @@ F32 LLStatAccum::meanValue(TimeScale scale) const
- {
- return 0.0;
- }
-- if ( scale == SCALE_PER_FRAME )
-- { // Per-frame not supported here
-- scale = SCALE_100MS;
-- }
--
-- if (scale < 0 || scale >= NUM_SCALES)
-+ if (scale < 0 || scale >= IMPL_NUM_SCALES)
- {
- llwarns << "llStatAccum::meanValue called for unsupported scale: "
- << scale << llendl;
-@@ -536,15 +260,12 @@ void LLStatMeasure::sample(F64 value)
-
- // ------------------------------------------------------------------------
-
--LLStatTime::LLStatTime(const std::string & key)
-- : LLStatAccum(false),
-- mFrameNumber(LLFrameTimer::getFrameCount()),
-- mTotalTimeInFrame(0),
-- mKey(key)
--#if LL_DEBUG
-- , mRunning(FALSE)
--#endif
-+LLStatTime::LLStatTime(bool use_frame_timer)
-+ : LLStatAccum(use_frame_timer),
-+ mFrameNumber(0),
-+ mTotalTimeInFrame(0)
- {
-+ mFrameNumber = LLFrameTimer::getFrameCount();
- }
-
- void LLStatTime::start()
-@@ -558,12 +279,6 @@ void LLStatTime::start()
- }
-
- sum(0.0);
--
--#if LL_DEBUG
-- // Shouldn't be running already
-- llassert( !mRunning );
-- mRunning = TRUE;
--#endif
- }
-
- void LLStatTime::stop()
-@@ -571,149 +286,7 @@ void LLStatTime::stop()
- U64 end_time = getCurrentUsecs();
- U64 duration = end_time - mLastTime;
- sum(F64(duration), end_time);
-- //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl;
- mTotalTimeInFrame += duration;
--
--#if LL_DEBUG
-- mRunning = FALSE;
--#endif
--}
--
--/* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const
--{
-- if ( LLStatAccum::SCALE_PER_FRAME == scale )
-- {
-- return mTotalTimeInFrame;
-- }
-- else
-- {
-- return LLStatAccum::meanValue(scale);
-- }
--}
--
--
--// ------------------------------------------------------------------------
--
--
--// Use this constructor for pre-defined LLStatTime objects
--LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL)
--{
-- if (mPredefinedStat)
-- {
-- // If dynamic stats are turned on, this will create a separate entry in the stat map.
-- initDynamicStat(mPredefinedStat->mKey);
--
-- // Start predefined stats. These stats are not part of the stat map.
-- mPredefinedStat->start();
-- }
--}
--
--// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
--// These are also turned on or off via the switch passed in
--LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
--{
-- if (!sStatsEnabled) return;
--
-- if (NULL == key2 || strlen(key2) == 0)
-- {
-- initDynamicStat(key1);
-- }
-- else
-- {
-- std::ostringstream key;
-- key << key1 << "_" << key2;
-- initDynamicStat(key.str());
-- }
--}
--
--void LLPerfBlock::initDynamicStat(const std::string& key)
--{
-- // Early exit if dynamic stats aren't enabled.
-- if (!sStatsEnabled) return;
--
-- mLastPath = sCurrentStatPath; // Save and restore current path
-- sCurrentStatPath += "/" + key; // Add key to current path
--
-- // See if the LLStatTime object already exists
-- stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath);
-- if ( iter == sStatMap.end() )
-- {
-- // StatEntry object doesn't exist, so create it
-- mDynamicStat = new StatEntry( key );
-- sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path
-- }
-- else
-- {
-- // Found this path in the map, use the object there
-- mDynamicStat = (*iter).second; // Get StatEntry for the current path
-- }
--
-- if (mDynamicStat)
-- {
-- mDynamicStat->mStat.start();
-- mDynamicStat->mCount++;
-- }
-- else
-- {
-- llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl;
-- sCurrentStatPath = mLastPath;
-- }
--}
--
--
--// Destructor does the time accounting
--LLPerfBlock::~LLPerfBlock()
--{
-- if (mPredefinedStat) mPredefinedStat->stop();
-- if (mDynamicStat)
-- {
-- mDynamicStat->mStat.stop();
-- sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block
-- }
--}
--
--
--// Clear the map of any dynamic stats. Static routine
--void LLPerfBlock::clearDynamicStats()
--{
-- std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer());
-- sStatMap.clear();
--}
--
--// static - Extract the stat info into LLSD
--void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
-- LLStatAccum::TimeScale scale )
--{
-- // If we aren't in per-frame scale, we need to go from second to microsecond.
-- U32 scale_adjustment = 1;
-- if (LLStatAccum::SCALE_PER_FRAME != scale)
-- {
-- scale_adjustment = USEC_PER_SEC;
-- }
-- stat_map_t::iterator iter = sStatMap.begin();
-- for ( ; iter != sStatMap.end(); ++iter )
-- { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time
-- const std::string & stats_full_path = (*iter).first;
--
-- StatEntry * stat = (*iter).second;
-- if (stat)
-- {
-- if (stat->mCount > 0)
-- {
-- stats[stats_full_path] = LLSD::emptyMap();
-- stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale));
-- if (stat->mCount > 1)
-- {
-- stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount;
-- }
-- stat->mCount = 0;
-- }
-- }
-- else
-- { // WTF? Shouldn't have a NULL pointer in the map.
-- llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
-- }
-- }
- }
-
-
-diff --git a/linden/indra/llcommon/llstat.h b/linden/indra/llcommon/llstat.h
-index eceb5e3..0e66cf0 100644
---- a/linden/indra/llcommon/llstat.h
-+++ b/linden/indra/llcommon/llstat.h
-@@ -33,13 +33,9 @@
- #define LL_LLSTAT_H
-
- #include
--#include
-
- #include "lltimer.h"
- #include "llframetimer.h"
--#include "llfile.h"
--
--class LLSD;
-
- // Set this if longer stats are needed
- #define ENABLE_LONG_TIME_STATS 0
-@@ -62,18 +58,19 @@ public:
- SCALE_100MS,
- SCALE_SECOND,
- SCALE_MINUTE,
-+ SCALE_TWO_MINUTE,
- #if ENABLE_LONG_TIME_STATS
- SCALE_HOUR,
- SCALE_DAY,
- SCALE_WEEK,
- #endif
-- NUM_SCALES, // Use to size storage arrays
-- SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets
-+ NUM_SCALES
- };
-
-- static U64 sScaleTimes[NUM_SCALES];
-+ static const TimeScale IMPL_NUM_SCALES = (TimeScale)(SCALE_TWO_MINUTE + 1);
-+ static U64 sScaleTimes[IMPL_NUM_SCALES];
-
-- virtual F32 meanValue(TimeScale scale) const;
-+ F32 meanValue(TimeScale scale) const;
- // see the subclasses for the specific meaning of value
-
- F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); }
-@@ -89,8 +86,8 @@ public:
- // Get current microseconds based on timer type
-
- BOOL mUseFrameTimer;
-- BOOL mRunning;
-
-+ BOOL mRunning;
- U64 mLastTime;
-
- struct Bucket
-@@ -102,7 +99,7 @@ public:
- F64 lastAccum;
- };
-
-- Bucket mBuckets[NUM_SCALES];
-+ Bucket mBuckets[IMPL_NUM_SCALES];
-
- BOOL mLastSampleValid;
- F64 mLastSampleValue;
-@@ -139,115 +136,37 @@ public:
- };
-
-
-+class LLTimeBlock;
-+
- class LLStatTime : public LLStatAccum
- // gathers statistics about time spent in a block of code
- // measure average duration per second in the block
- {
- public:
-- LLStatTime( const std::string & key = "undefined" );
-+ LLStatTime(bool use_frame_timer = false);
-
- U32 mFrameNumber; // Current frame number
- U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame
-
-- void setKey( const std::string & key ) { mKey = key; };
--
-- virtual F32 meanValue(TimeScale scale) const;
--
- private:
-- void start(); // Start and stop measuring time block
-+ void start();
- void stop();
--
-- std::string mKey; // Tag representing this time block
--
--#if LL_DEBUG
-- BOOL mRunning; // TRUE if start() has been called
--#endif
--
-- friend class LLPerfBlock;
-+ friend class LLTimeBlock;
- };
-
--// ----------------------------------------------------------------------------
--
--
--// Use this class on the stack to record statistics about an area of code
--class LLPerfBlock
-+class LLTimeBlock
- {
- public:
-- struct StatEntry
-- {
-- StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {}
-- LLStatTime mStat;
-- U32 mCount;
-- };
-- typedef std::map stat_map_t;
--
-- // Use this constructor for pre-defined LLStatTime objects
-- LLPerfBlock(LLStatTime* stat);
--
-- // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
-- LLPerfBlock( const char* key1, const char* key2 = NULL);
--
--
-- ~LLPerfBlock();
--
-- static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; };
-- static S32 getStatsEnabled() { return sStatsEnabled; };
--
-- static void clearDynamicStats(); // Reset maps to clear out dynamic objects
-- static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin
-- LLStatAccum::TimeScale scale );
--
-+ LLTimeBlock(LLStatTime& stat) : mStat(stat) { mStat.start(); }
-+ ~LLTimeBlock() { mStat.stop(); }
- private:
-- // Initialize dynamically created LLStatTime objects
-- void initDynamicStat(const std::string& key);
--
-- std::string mLastPath; // Save sCurrentStatPath when this is called
-- LLStatTime * mPredefinedStat; // LLStatTime object to get data
-- StatEntry * mDynamicStat; // StatEntryobject to get data
--
-- static BOOL sStatsEnabled; // Normally FALSE
-- static stat_map_t sStatMap; // Map full path string to LLStatTime objects
-- static std::string sCurrentStatPath; // Something like "frame/physics/physics step"
-+ LLStatTime& mStat;
- };
-
--// ----------------------------------------------------------------------------
-
--class LLPerfStats
--{
--public:
-- LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
-- virtual ~LLPerfStats();
--
-- virtual void init(); // Reset and start all stat timers
-- virtual void updatePerFrameStats();
-- // Override these function to add process-specific information to the performance log header and per-frame logging.
-- virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ }
-- virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ }
--
-- // High-resolution frame stats
-- BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); };
-- F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; };
-- void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; };
-- void setReportPerformanceDuration( F32 seconds );
-- void setProcessName(const std::string& process_name) { mProcessName = process_name; }
-- void setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
--
--protected:
-- void openPerfStatsFile(); // Open file for high resolution metrics logging
-- void dumpIntervalPerformanceStats();
-
-- llofstream mFrameStatsFile; // File for per-frame stats
-- BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts
-- BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report
-- std::string mProcessName;
-- S32 mProcessPID;
-
--private:
-- F32 mReportPerformanceStatInterval; // Seconds between performance stats
-- F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats
--};
-
--// ----------------------------------------------------------------------------
- class LLStat
- {
- public:
-diff --git a/linden/indra/llcommon/llstatenums.h b/linden/indra/llcommon/llstatenums.h
-index febd958..ae3be14 100644
---- a/linden/indra/llcommon/llstatenums.h
-+++ b/linden/indra/llcommon/llstatenums.h
-@@ -33,41 +33,38 @@
-
- enum
- {
-- LL_SIM_STAT_TIME_DILATION, // 0
-+ LL_SIM_STAT_TIME_DILATION,
- LL_SIM_STAT_FPS,
- LL_SIM_STAT_PHYSFPS,
- LL_SIM_STAT_AGENTUPS,
- LL_SIM_STAT_FRAMEMS,
-- LL_SIM_STAT_NETMS, // 5
-+ LL_SIM_STAT_NETMS,
- LL_SIM_STAT_SIMOTHERMS,
- LL_SIM_STAT_SIMPHYSICSMS,
- LL_SIM_STAT_AGENTMS,
- LL_SIM_STAT_IMAGESMS,
-- LL_SIM_STAT_SCRIPTMS, // 10
-+ LL_SIM_STAT_SCRIPTMS,
- LL_SIM_STAT_NUMTASKS,
- LL_SIM_STAT_NUMTASKSACTIVE,
- LL_SIM_STAT_NUMAGENTMAIN,
- LL_SIM_STAT_NUMAGENTCHILD,
-- LL_SIM_STAT_NUMSCRIPTSACTIVE, // 15
-+ LL_SIM_STAT_NUMSCRIPTSACTIVE,
- LL_SIM_STAT_LSLIPS,
- LL_SIM_STAT_INPPS,
- LL_SIM_STAT_OUTPPS,
- LL_SIM_STAT_PENDING_DOWNLOADS,
-- LL_SIM_STAT_PENDING_UPLOADS, // 20
-+ LL_SIM_STAT_PENDING_UPLOADS,
- LL_SIM_STAT_VIRTUAL_SIZE_KB,
- LL_SIM_STAT_RESIDENT_SIZE_KB,
- LL_SIM_STAT_PENDING_LOCAL_UPLOADS,
- LL_SIM_STAT_TOTAL_UNACKED_BYTES,
-- LL_SIM_STAT_PHYSICS_PINNED_TASKS, // 25
-+ LL_SIM_STAT_PHYSICS_PINNED_TASKS,
- LL_SIM_STAT_PHYSICS_LOD_TASKS,
- LL_SIM_STAT_SIMPHYSICSSTEPMS,
- LL_SIM_STAT_SIMPHYSICSSHAPEMS,
- LL_SIM_STAT_SIMPHYSICSOTHERMS,
-- LL_SIM_STAT_SIMPHYSICSMEMORY, // 30
-+ LL_SIM_STAT_SIMPHYSICSMEMORY,
- LL_SIM_STAT_SCRIPT_EPS,
-- LL_SIM_STAT_SIMSPARETIME,
-- LL_SIM_STAT_SIMSLEEPTIME,
-- LL_SIM_STAT_IOPUMPTIME,
- };
-
- #endif
-diff --git a/linden/indra/llmessage/lliohttpserver.cpp b/linden/indra/llmessage/lliohttpserver.cpp
-index 167f212..39fecb4 100644
---- a/linden/indra/llmessage/lliohttpserver.cpp
-+++ b/linden/indra/llmessage/lliohttpserver.cpp
-@@ -47,7 +47,6 @@
- #include "llpumpio.h"
- #include "llsd.h"
- #include "llsdserialize_xml.h"
--#include "llstat.h"
- #include "llstl.h"
- #include "lltimer.h"
-
-@@ -172,26 +171,22 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
- std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
- if(verb == HTTP_VERB_GET)
- {
-- LLPerfBlock getblock("http_get");
- mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else if(verb == HTTP_VERB_PUT)
- {
-- LLPerfBlock putblock("http_put");
- LLSD input;
- LLSDSerialize::fromXML(input, istr);
- mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
- }
- else if(verb == HTTP_VERB_POST)
- {
-- LLPerfBlock postblock("http_post");
- LLSD input;
- LLSDSerialize::fromXML(input, istr);
- mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
- }
- else if(verb == HTTP_VERB_DELETE)
- {
-- LLPerfBlock delblock("http_delete");
- mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else if(verb == HTTP_VERB_OPTIONS)
-diff --git a/linden/indra/llmessage/llmessagetemplate.h b/linden/indra/llmessage/llmessagetemplate.h
-index 2390eea..a4062fa 100644
---- a/linden/indra/llmessage/llmessagetemplate.h
-+++ b/linden/indra/llmessage/llmessagetemplate.h
-@@ -34,8 +34,11 @@
-
- #include "lldarray.h"
- #include "message.h" // TODO: babbage: Remove...
--#include "llstat.h"
-+#include "llmsgvariabletype.h"
- #include "llstl.h"
-+#include
-+#include
-+#include
-
- class LLMsgVarData
- {
-@@ -270,6 +273,31 @@ enum EMsgDeprecation
- MD_DEPRECATED
- };
-
-+class LLMessageTemplateHandlerEntry
-+{
-+public:
-+ LLMessageTemplateHandlerEntry(message_handler_func_t handler, void **userdata = NULL) :
-+ mHandlerFunc(handler), mUserData(userdata) {}
-+
-+ void call(LLMessageSystem *msgsystem) const { mHandlerFunc(msgsystem, mUserData); }
-+
-+ bool operator==(const LLMessageTemplateHandlerEntry&a) { return mHandlerFunc == a.mHandlerFunc; }
-+private:
-+ // message handler function (this is set by each application)
-+ message_handler_func_t mHandlerFunc;
-+ void **mUserData;
-+};
-+
-+class callHandler : public std::unary_function
-+{
-+public:
-+ callHandler(LLMessageSystem *msg) : mMsg(msg) {}
-+ void operator()(const LLMessageTemplateHandlerEntry& a) const { a.call(mMsg); }
-+private:
-+ LLMessageSystem *mMsg;
-+};
-+
-+
- class LLMessageTemplate
- {
- public:
-@@ -291,9 +319,10 @@ public:
- mTotalDecodeTime(0.f),
- mMaxDecodeTimePerMsg(0.f),
- mBanFromTrusted(false),
-- mBanFromUntrusted(false),
-- mHandlerFunc(NULL),
-- mUserData(NULL)
-+ //mBanFromUntrusted(false),
-+ //mHandlerFunc(NULL),
-+ //mUserData(NULL)
-+ mBanFromUntrusted(false)
- {
- mName = LLMessageStringTable::getInstance()->getString(name);
- }
-@@ -361,21 +390,91 @@ public:
- return mDeprecation;
- }
-
-- void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
-+// void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
-+ /**
-+ * @brief Adds a handler
-+ * This function adds a new handler to be called when the message arrives.
-+ * Repeated additions of the same handler function will be ignored.
-+ * @note delHandlerFunc() must be called to remove the registration
-+ * @param handler Function to call
-+ * @param user_data User specified data to pass to the function
-+ */
-+ void addHandlerFunc(message_handler_func_t handler, void **user_data)
- {
-- mHandlerFunc = handler_func;
-- mUserData = user_data;
-+ LLMessageTemplateHandlerEntry h(handler, user_data);
-+
-+ if ( std::find(mHandlers.begin(), mHandlers.end(), h ) != mHandlers.end() )
-+ {
-+ return;
-+ }
-+
-+ mHandlers.push_back( h );
-+ }
-+
-+ /**
-+ * @brief Sets a handler
-+ * This function sets a handler to be called when the message arrives.
-+ * Any existing handlers are unregistered.
-+ * @note delHandlerFunc() must be called to remove the registration
-+ * @param handler Function to call
-+ * @param user_data User specified data to pass to the function
-+ */
-+ void setHandlerFunc(message_handler_func_t handler, void **user_data)
-+ {
-+ mHandlers.clear();
-+ if( handler )
-+ {
-+ addHandlerFunc(handler, user_data);
-+ }
-+ else
-+ {
-+ llwarns << "code has reset handler for \"" << mName << "\" by setting it to NULL." << llendl;
-+ }
-+ }
-+
-+ /**
-+ * @brief Removes a handler
-+ * Removes a handler from the list of handlers.
-+ * Attempts to remove handlers that aren't in the list are silently
-+ * ignored.
-+ * @param handler Function to remove
-+ */
-+ void delHandlerFunc(message_handler_func_t handler)
-+ {
-+ //mHandlerFunc = handler_func;
-+ //mUserData = user_data;
-+ mHandlers.remove( LLMessageTemplateHandlerEntry(handler) );
- }
-
- BOOL callHandlerFunc(LLMessageSystem *msgsystem) const
- {
-- if (mHandlerFunc)
-+ //if (mHandlerFunc)
-+ if ( mHandlers.empty() )
-+ {
-+ return FALSE;
-+ }
-+ /*
-+ * Be on the safe side and use for_each only when necessary. There is Linden code ("ReplyPayPrice") that
-+ * does not take the multiple reply handlers into account and simply tries to unregister
-+ * by setting the handler function to 0, unfortunately from within the reply handler so in this case
-+ * the for_each iterator inside std_algo.h is invalidated leading to a crash if the memory is reused
-+ * in between.
-+ */
-+ else if( mHandlers.size() == 1 )
-+ {
-+ //KOW HACK we probably want to re-enable the llPerfBlocks here, may need a vendor merge for llstats.cpp stuff.
-+ //LLPerfBlock msg_cb_time("msg_cb", mName);
-+ //mHandlerFunc(msgsystem, mUserData);
-+ mHandlers.begin()->call(msgsystem);
-+ return TRUE;
-+ }
-+ else
- {
-- LLPerfBlock msg_cb_time("msg_cb", mName);
-- mHandlerFunc(msgsystem, mUserData);
-+ //LLPerfBlock msg_cb_time("msg_cb", mName);
-+ std::for_each(mHandlers.begin(), mHandlers.end(), callHandler(msgsystem));
- return TRUE;
- }
-- return FALSE;
-+ //return FALSE;
- }
-
- bool isUdpBanned() const
-@@ -421,8 +520,9 @@ public:
-
- private:
- // message handler function (this is set by each application)
-- void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
-- void **mUserData;
-+// void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
-+// void **mUserData;
-+ std::list mHandlers;
- };
-
- #endif // LL_LLMESSAGETEMPLATE_H
-diff --git a/linden/indra/llmessage/llpumpio.cpp b/linden/indra/llmessage/llpumpio.cpp
-index 01a43ec..cc9e543 100644
---- a/linden/indra/llmessage/llpumpio.cpp
-+++ b/linden/indra/llmessage/llpumpio.cpp
-@@ -41,7 +41,6 @@
- #include "llapr.h"
- #include "llmemtype.h"
- #include "llstl.h"
--#include "llstat.h"
-
- // These should not be enabled in production, but they can be
- // intensely useful during development for finding certain kinds of
-@@ -177,8 +176,7 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) :
- mCurrentPool(NULL),
- mCurrentPoolReallocCount(0),
- mChainsMutex(NULL),
-- mCallbackMutex(NULL),
-- mCurrentChain(mRunningChains.end())
-+ mCallbackMutex(NULL)
- {
- LLMemType m1(LLMemType::MTYPE_IO_PUMP);
- initialize(pool);
-@@ -274,10 +272,7 @@ bool LLPumpIO::setTimeoutSeconds(F32 timeout)
- void LLPumpIO::adjustTimeoutSeconds(F32 delta)
- {
- // If no chain is running, bail
-- if(mRunningChains.end() == mCurrentChain)
-- {
-- return;
-- }
-+ if(current_chain_t() == mCurrentChain) return;
- (*mCurrentChain).adjustTimeoutSeconds(delta);
- }
-
-@@ -526,10 +521,7 @@ void LLPumpIO::pump(const S32& poll_timeout)
- //llinfos << "polling" << llendl;
- S32 count = 0;
- S32 client_id = 0;
-- {
-- LLPerfBlock polltime("pump_poll");
- apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
-- }
- PUMP_DEBUG;
- for(S32 ii = 0; ii < count; ++ii)
- {
-diff --git a/linden/indra/llmessage/message.cpp b/linden/indra/llmessage/message.cpp
-index ccc3d79..0d0ad18 100644
---- a/linden/indra/llmessage/message.cpp
-+++ b/linden/indra/llmessage/message.cpp
-@@ -754,7 +754,6 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
- clearReceiveState();
- valid_packet = FALSE;
- }
--
- if( valid_packet && mTemplateMessageReader->isUdpBanned())
- {
- llwarns << "Received UDP black listed message "
-@@ -767,6 +766,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count )
- if( valid_packet )
- {
- logValidMsg(cdp, host, recv_reliable, recv_resent, (BOOL)(acks>0) );
-+
- valid_packet = mTemplateMessageReader->readMessage(buffer, host);
- }
-
-@@ -2972,7 +2972,7 @@ void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
- }
-
-
--void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
-+void LLMessageSystem::setHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
- {
- LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
- if (msgtemplate)
-@@ -2985,6 +2985,32 @@ void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(
- }
- }
-
-+void LLMessageSystem::addHandlerFuncFast(const char *name, message_handler_func_t handler_func, void **user_data)
-+{
-+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
-+ if (msgtemplate)
-+ {
-+ msgtemplate->addHandlerFunc(handler_func, user_data);
-+ }
-+ else
-+ {
-+ llerrs << name << " is not a known message name!" << llendl;
-+ }
-+}
-+
-+void LLMessageSystem::delHandlerFuncFast(const char *name, message_handler_func_t handler_func)
-+{
-+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
-+ if (msgtemplate)
-+ {
-+ msgtemplate->delHandlerFunc(handler_func);
-+ }
-+ else
-+ {
-+ llerrs << name << " is not a known message name!" << llendl;
-+ }
-+}
-+
- bool LLMessageSystem::callHandler(const char *name,
- bool trustedSource, LLMessageSystem* msg)
- {
-@@ -3956,27 +3982,27 @@ void LLMessageSystem::getString(const char *block, const char *var,
- blocknum);
- }
-
--BOOL LLMessageSystem::has(const char *blockname) const
-+BOOL LLMessageSystem::has(const char *blockname)
- {
- return getNumberOfBlocks(blockname) > 0;
- }
-
--S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
-+S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname)
- {
- return mMessageReader->getNumberOfBlocks(blockname);
- }
-
--S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
-+S32 LLMessageSystem::getNumberOfBlocks(const char *blockname)
- {
- return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
- }
-
--S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
-+S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname)
- {
- return mMessageReader->getSize(blockname, varname);
- }
-
--S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
-+S32 LLMessageSystem::getSize(const char *blockname, const char *varname)
- {
- return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
- LLMessageStringTable::getInstance()->getString(varname));
-@@ -3984,13 +4010,13 @@ S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
-
- // size in bytes of variable length data
- S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
-- const char *varname) const
-+ const char *varname)
- {
- return mMessageReader->getSize(blockname, blocknum, varname);
- }
-
- S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
-- const char *varname) const
-+ const char *varname)
- {
- return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
- LLMessageStringTable::getInstance()->getString(varname));
-diff --git a/linden/indra/llmessage/message.h b/linden/indra/llmessage/message.h
-index c503a58..4b96526 100644
---- a/linden/indra/llmessage/message.h
-+++ b/linden/indra/llmessage/message.h
-@@ -179,7 +179,7 @@ enum EMessageException
- MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
- };
- typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
--
-+typedef void (*message_handler_func_t)(LLMessageSystem *msgsystem, void **user_data);
-
- // message data pieces are used to collect the data called for by the message template
- class LLMsgData;
-@@ -299,12 +299,24 @@ public:
-
-
- // methods for building, sending, receiving, and handling messages
-- void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
-- void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
-+ void setHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
-+ void setHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
- {
- setHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
- }
-
-+ void addHandlerFuncFast(const char *name, message_handler_func_t, void **user_data = NULL);
-+ void addHandlerFunc(const char *name, message_handler_func_t handler_func, void **user_data = NULL)
-+ {
-+ addHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
-+ }
-+
-+ void delHandlerFuncFast(const char *name, message_handler_func_t);
-+ void delHandlerFunc(const char *name, message_handler_func_t handler_func)
-+ {
-+ delHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func);
-+ }
-+
- // Set a callback function for a message system exception.
- void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
- // Call the specified exception func, and return TRUE if a
-@@ -594,14 +606,14 @@ public:
- LLHost findHost(const U32 circuit_code);
- void sanityCheck();
-
-- BOOL has(const char *blockname) const;
-- S32 getNumberOfBlocksFast(const char *blockname) const;
-- S32 getNumberOfBlocks(const char *blockname) const;
-- S32 getSizeFast(const char *blockname, const char *varname) const;
-- S32 getSize(const char *blockname, const char *varname) const;
-+ BOOL has(const char *blockname);
-+ S32 getNumberOfBlocksFast(const char *blockname);
-+ S32 getNumberOfBlocks(const char *blockname);
-+ S32 getSizeFast(const char *blockname, const char *varname);
-+ S32 getSize(const char *blockname, const char *varname);
- S32 getSizeFast(const char *blockname, S32 blocknum,
-- const char *varname) const; // size in bytes of data
-- S32 getSize(const char *blockname, S32 blocknum, const char *varname) const;
-+ const char *varname); // size in bytes of data
-+ S32 getSize(const char *blockname, S32 blocknum, const char *varname);
-
- void resetReceiveCounts(); // resets receive counts for all message types to 0
- void dumpReceiveCounts(); // dumps receive count for each message type to llinfos
-diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
-index cf9a7cd..4927571 100644
---- a/linden/indra/newview/app_settings/settings.xml
-+++ b/linden/indra/newview/app_settings/settings.xml
-@@ -4762,7 +4762,7 @@
- Type
- U32
- Value
-- 0
-+ 1
-
- MemoryLogFrequency
-
-diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
-index cab9815..5cd2a56 100644
---- a/linden/indra/newview/llstartup.cpp
-+++ b/linden/indra/newview/llstartup.cpp
-@@ -3152,7 +3152,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)
- msg->setHandlerFunc("ParcelDwellReply",
- LLViewerParcelMgr::processParcelDwellReply);
-
-- msg->setHandlerFunc("AvatarPropertiesReply",
-+ msg->addHandlerFunc("AvatarPropertiesReply",
- LLPanelAvatar::processAvatarPropertiesReply);
- msg->setHandlerFunc("AvatarInterestsReply",
- LLPanelAvatar::processAvatarInterestsReply);
-diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp
-index 03114f7..b984687 100644
---- a/linden/indra/newview/llviewermessage.cpp
-+++ b/linden/indra/newview/llviewermessage.cpp
-@@ -3516,15 +3516,6 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
- case LL_SIM_STAT_SIMPHYSICSMEMORY:
- LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value);
- break;
-- case LL_SIM_STAT_SIMSPARETIME:
-- LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value);
-- break;
-- case LL_SIM_STAT_SIMSLEEPTIME:
-- LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value);
-- break;
-- case LL_SIM_STAT_IOPUMPTIME:
-- LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value);
-- break;
- default:
- // Used to be a commented out warning.
- LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL;
-diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h
-index dc529cd..ebb46b9 100644
---- a/linden/indra/newview/llviewerobject.h
-+++ b/linden/indra/newview/llviewerobject.h
-@@ -600,7 +600,9 @@ protected:
- // extra data sent from the sim...currently only used for tree species info
- U8* mData;
-
-+public:
- LLPointer mPartSourcep; // Particle source associated with this object.
-+protected:
- LLAudioSourceVO* mAudioSourcep;
- F32 mAudioGain;
-
-diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp
-index 3d2523e..86993df 100644
---- a/linden/indra/newview/llvoavatar.cpp
-+++ b/linden/indra/newview/llvoavatar.cpp
-@@ -891,7 +891,6 @@ LLVOAvatar::LLVOAvatar(
- mEyeBallLeftMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
- mEyeBallRightMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
- mEyeBallRightMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
--
- //-------------------------------------------------------------------------
- // register motions
- //-------------------------------------------------------------------------
-@@ -960,7 +959,8 @@ LLVOAvatar::LLVOAvatar(
- //VTPause(); // VTune
-
- mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
-- mCurrentGesticulationLevel = 0;
-+ mCurrentGesticulationLevel = 0;
-+
- }
-
- //------------------------------------------------------------------------
-@@ -1990,7 +1990,8 @@ void LLVOAvatar::buildCharacter()
- mWristRightp = (LLViewerJoint*)mRoot.findJoint("mWristRight");
- mEyeLeftp = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
- mEyeRightp = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
--
-+
-+ lldebugs << " initialized joint pointers" << llendl;
- //-------------------------------------------------------------------------
- // Make sure "well known" pointers exist
- //-------------------------------------------------------------------------
-@@ -2016,7 +2017,7 @@ void LLVOAvatar::buildCharacter()
- llerrs << "Failed to create avatar." << llendl;
- return;
- }
--
-+ lldebugs << "pointers exist, good." << llendl;
- //-------------------------------------------------------------------------
- // initialize the pelvis
- //-------------------------------------------------------------------------
-@@ -2140,7 +2141,7 @@ void LLVOAvatar::buildCharacter()
- }
- }
- }
--
-+ lldebugs << "builded the attach and detach menus" << llendl;
- // add screen attachments
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
-@@ -2159,6 +2160,7 @@ void LLVOAvatar::buildCharacter()
- &handle_detach_from_avatar, object_attached, attachment));
- }
- }
-+ lldebugs << "added screen attachments" << llendl;
-
- for (S32 pass = 0; pass < 2; pass++)
- {
-@@ -2188,6 +2190,7 @@ void LLVOAvatar::buildCharacter()
- gDetachSubMenu->appendSeparator();
- }
- }
-+ lldebugs << "added other attachments" << llendl;
-
- for (S32 group = 0; group < 8; group++)
- {
-@@ -2241,9 +2244,11 @@ void LLVOAvatar::buildCharacter()
- }
- }
- }
-+ lldebugs << "added pies" << llendl;
- }
-
- mMeshValid = TRUE;
-+ lldebugs << "mMeshValid = TRUE" << llendl;
- }
-
-
diff --git a/meerkat-pipeline.cpp.diff.txt b/meerkat-pipeline.cpp.diff.txt
deleted file mode 100644
index b34cd94..0000000
--- a/meerkat-pipeline.cpp.diff.txt
+++ /dev/null
@@ -1,22 +0,0 @@
---- /linden/indra/newview/pipeline.cpp 2009-06-25 15:23:44.000000000 +0200
-+++ /linden/indra/newview/pipeline.cpp 2009-06-25 23:49:51.000000000 +0200
-@@ -2691,7 +2711,10 @@
- // from Medium -> Low, because we unload all the shaders and the
- // draw pools aren't aware. I don't know if this has to be a separate
- // loop before actual rendering. JC
-- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-+
-+ // TODO: this is a useful fix, find out why it breaks logout -- RMS
-+
-+/* for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (poolp->isFacePool() && hasRenderType(poolp->getType()))
-@@ -2699,6 +2722,7 @@
- poolp->prerender();
- }
- }
-+*/
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
diff --git a/meerkat-voice.diff.txt b/meerkat-voice.diff.txt
deleted file mode 100644
index f49d511..0000000
--- a/meerkat-voice.diff.txt
+++ /dev/null
@@ -1,7282 +0,0 @@
-diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp
-index bf1f678..41137b4 100644
---- a/linden/indra/newview/llfloaterfriends.cpp
-+++ b/linden/indra/newview/llfloaterfriends.cpp
-@@ -57,7 +57,6 @@
- #include "llviewermessage.h"
- #include "lltimer.h"
- #include "lltextbox.h"
--#include "llvoiceclient.h"
-
- //Maximum number of people you can select to do an operation on at once.
- #define MAX_FRIEND_SELECT 20
-@@ -65,8 +64,6 @@
- #define RIGHTS_CHANGE_TIMEOUT 5.0
- #define OBSERVER_TIMEOUT 0.5
-
--#define ONLINE_SIP_ICON_NAME "slim_icon_16_viewer.tga"
--
- // simple class to observe the calling cards.
- class LLLocalFriendsObserver : public LLFriendObserver, public LLEventTimer
- {
-@@ -114,14 +111,10 @@ LLPanelFriends::LLPanelFriends() :
- mEventTimer.stop();
- mObserver = new LLLocalFriendsObserver(this);
- LLAvatarTracker::instance().addObserver(mObserver);
-- // For notification when SIP online status changes.
-- LLVoiceClient::getInstance()->addObserver(mObserver);
- }
-
- LLPanelFriends::~LLPanelFriends()
- {
-- // For notification when SIP online status changes.
-- LLVoiceClient::getInstance()->removeObserver(mObserver);
- LLAvatarTracker::instance().removeObserver(mObserver);
- delete mObserver;
- }
-@@ -219,9 +212,7 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
- LLAvatarTracker& at = LLAvatarTracker::instance();
- const LLRelationship* relationInfo = at.getBuddyInfo(agent_id);
- if(!relationInfo) return FALSE;
--
-- bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(agent_id);
-- bool isOnline = relationInfo->isOnline();
-+ BOOL online = relationInfo->isOnline();
-
- std::string fullname;
- BOOL have_name = gCacheName->getFullName(agent_id, fullname);
-@@ -237,17 +228,12 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id)
- LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS];
- online_status_column["column"] = "icon_online_status";
- online_status_column["type"] = "icon";
--
-- if (isOnline)
-+
-+ if (online)
- {
- friend_column["font-style"] = "BOLD";
- online_status_column["value"] = "icon_avatar_online.tga";
- }
-- else if(isOnlineSIP)
-- {
-- friend_column["font-style"] = "BOLD";
-- online_status_column["value"] = ONLINE_SIP_ICON_NAME;
-- }
-
- LLSD& online_column = element["columns"][LIST_VISIBLE_ONLINE];
- online_column["column"] = "icon_visible_online";
-@@ -285,30 +271,14 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh
- if (!info) return FALSE;
- LLScrollListItem* itemp = mFriendsList->getItem(agent_id);
- if (!itemp) return FALSE;
--
-- bool isOnlineSIP = LLVoiceClient::getInstance()->isOnlineSIP(itemp->getUUID());
-- bool isOnline = info->isOnline();
-
- std::string fullname;
- BOOL have_name = gCacheName->getFullName(agent_id, fullname);
--
-- // Name of the status icon to use
-- std::string statusIcon;
--
-- if(isOnline)
-- {
-- statusIcon = "icon_avatar_online.tga";
-- }
-- else if(isOnlineSIP)
-- {
-- statusIcon = ONLINE_SIP_ICON_NAME;
-- }
-
-- itemp->getColumn(LIST_ONLINE_STATUS)->setValue(statusIcon);
--
-+ itemp->getColumn(LIST_ONLINE_STATUS)->setValue(info->isOnline() ? std::string("icon_avatar_online.tga") : LLStringUtil::null);
- itemp->getColumn(LIST_FRIEND_NAME)->setValue(fullname);
- // render name of online friends in bold text
-- ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle((isOnline || isOnlineSIP) ? LLFontGL::BOLD : LLFontGL::NORMAL);
-+ ((LLScrollListText*)itemp->getColumn(LIST_FRIEND_NAME))->setFontStyle(info->isOnline() ? LLFontGL::BOLD : LLFontGL::NORMAL);
- itemp->getColumn(LIST_VISIBLE_ONLINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS));
- itemp->getColumn(LIST_VISIBLE_MAP)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MAP_LOCATION));
- itemp->getColumn(LIST_EDIT_MINE)->setValue(info->isRightGrantedTo(LLRelationship::GRANT_MODIFY_OBJECTS));
-diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp
-index f30ae8c..d3139ad 100644
---- a/linden/indra/newview/llimpanel.cpp
-+++ b/linden/indra/newview/llimpanel.cpp
-@@ -49,7 +49,6 @@
- #include "llconsole.h"
- #include "llfloater.h"
- #include "llfloatergroupinfo.h"
--#include "llfloaterchatterbox.h"
- #include "llimview.h"
- #include "llinventory.h"
- #include "llinventorymodel.h"
-@@ -69,6 +68,7 @@
- #include "lluictrlfactory.h"
- #include "llviewerwindow.h"
- #include "lllogchat.h"
-+#include "llfloaterhtml.h"
- #include "llweb.h"
- #include "llhttpclient.h"
- #include "llmutelist.h"
-@@ -357,7 +357,7 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess
- llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
- }
-
-- LLVoiceClient::getInstance()->addObserver(this);
-+ LLVoiceClient::getInstance()->addStatusObserver(this);
- }
-
- LLVoiceChannel::~LLVoiceChannel()
-@@ -365,7 +365,7 @@ LLVoiceChannel::~LLVoiceChannel()
- // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
- if(gVoiceClient)
- {
-- gVoiceClient->removeObserver(this);
-+ gVoiceClient->removeStatusObserver(this);
- }
-
- sVoiceChannelMap.erase(mSessionID);
-@@ -983,8 +983,7 @@ void LLVoiceChannelP2P::activate()
- // otherwise answering the call
- else
- {
-- LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
--
-+ LLVoiceClient::getInstance()->answerInvite(mSessionHandle, mOtherUserID);
- // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
- mSessionHandle.clear();
- }
-@@ -1001,7 +1000,7 @@ void LLVoiceChannelP2P::getChannelInfo()
- }
-
- // receiving session from other user who initiated call
--void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
-+void LLVoiceChannelP2P::setSessionHandle(const std::string& handle)
- {
- BOOL needs_activate = FALSE;
- if (callStarted())
-@@ -1024,17 +1023,8 @@ void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::s
- }
-
- mSessionHandle = handle;
--
- // The URI of a p2p session should always be the other end's SIP URI.
-- if(!inURI.empty())
-- {
-- setURI(inURI);
-- }
-- else
-- {
-- setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
-- }
--
-+ setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
- mReceivedCall = TRUE;
-
- if (needs_activate)
-@@ -1171,7 +1161,6 @@ void LLFloaterIMPanel::init(const std::string& session_label)
- FALSE);
-
- setTitle(mSessionLabel);
--
- mInputEditor->setMaxTextLength(1023);
- // enable line history support for instant message bar
- mInputEditor->setEnableLineHistory(TRUE);
-@@ -1218,23 +1207,7 @@ LLFloaterIMPanel::~LLFloaterIMPanel()
- {
- delete mSpeakers;
- mSpeakers = NULL;
--
-- // End the text IM session if necessary
-- if(gVoiceClient && mOtherParticipantUUID.notNull())
-- {
-- switch(mDialog)
-- {
-- case IM_NOTHING_SPECIAL:
-- case IM_SESSION_P2P_INVITE:
-- gVoiceClient->endUserIMSession(mOtherParticipantUUID);
-- break;
--
-- default:
-- // Appease the compiler
-- break;
-- }
-- }
--
-+
- //kicks you out of the voice channel if it is currently active
-
- // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
-@@ -1424,7 +1397,6 @@ void LLFloaterIMPanel::draw()
- childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
- childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
- }
--
- LLFloater::draw();
- }
-
-@@ -1505,7 +1477,7 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
- if (!hostp->isFloaterFlashing(this))
- {
- hostp->setFloaterFlashing(this, TRUE);
-- LLFloaterChatterBox::markAsUnread(true);
-+//awfixme LLFloaterChatterBox::markAsUnread(true);
- }
-
- //// Only increment the number of unread IMs if they're from individuals
-@@ -1585,7 +1557,7 @@ void LLFloaterIMPanel::setVisible(BOOL b)
- if (hostp->isFloaterFlashing(this))
- {
- hostp->setFloaterFlashing(this, FALSE);
-- LLFloaterChatterBox::markAsUnread(false);
-+//awfixme LLFloaterChatterBox::markAsUnread(false);
-
- /* Don't change containing floater title - leave it "Instant Message" JC
- LLUIString title = sTitleString;
-@@ -1926,46 +1898,34 @@ void deliver_message(const std::string& utf8_text,
- EInstantMessage dialog)
- {
- std::string name;
-- bool sent = false;
- gAgent.buildFullname(name);
-
- const LLRelationship* info = NULL;
- info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id);
--
- U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE;
--
-- if((offline == IM_OFFLINE) && (LLVoiceClient::getInstance()->isOnlineSIP(other_participant_id)))
-- {
-- // User is online through the OOW connector, but not with a regular viewer. Try to send the message via SLVoice.
-- sent = gVoiceClient->sendTextMessage(other_participant_id, utf8_text);
-- }
--
-- if(!sent)
-- {
-- // Send message normally.
-
-- // default to IM_SESSION_SEND unless it's nothing special - in
-- // which case it's probably an IM to everyone.
-- U8 new_dialog = dialog;
-+ // default to IM_SESSION_SEND unless it's nothing special - in
-+ // which case it's probably an IM to everyone.
-+ U8 new_dialog = dialog;
-
-- if ( dialog != IM_NOTHING_SPECIAL )
-- {
-- new_dialog = IM_SESSION_SEND;
-- }
-- pack_instant_message(
-- gMessageSystem,
-- gAgent.getID(),
-- FALSE,
-- gAgent.getSessionID(),
-- other_participant_id,
-- name.c_str(),
-- utf8_text.c_str(),
-- offline,
-- (EInstantMessage)new_dialog,
-- im_session_id);
-- gAgent.sendReliableMessage();
-+ if ( dialog != IM_NOTHING_SPECIAL )
-+ {
-+ new_dialog = IM_SESSION_SEND;
- }
-
-+ pack_instant_message(
-+ gMessageSystem,
-+ gAgent.getID(),
-+ FALSE,
-+ gAgent.getSessionID(),
-+ other_participant_id,
-+ name,
-+ utf8_text,
-+ offline,
-+ (EInstantMessage)new_dialog,
-+ im_session_id);
-+ gAgent.sendReliableMessage();
-+
- // If there is a mute list and this is not a group chat...
- if ( LLMuteList::getInstance() )
- {
-diff --git a/linden/indra/newview/llimpanel.h b/linden/indra/newview/llimpanel.h
-index 0f9c0f3..afec6db 100644
---- a/linden/indra/newview/llimpanel.h
-+++ b/linden/indra/newview/llimpanel.h
-@@ -161,7 +161,7 @@ public:
- /*virtual*/ void activate();
- /*virtual*/ void getChannelInfo();
-
-- void setSessionHandle(const std::string& handle, const std::string &inURI);
-+ void setSessionHandle(const std::string& handle);
-
- protected:
- virtual void setState(EState state);
-@@ -295,6 +295,8 @@ private:
-
- void sendTypingState(BOOL typing);
-
-+ static LLFloaterIMPanel* sInstance;
-+
- private:
- LLLineEditor* mInputEditor;
- LLViewerTextEditor* mHistoryEditor;
-diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp
-index 1072b21..80c6d1c 100644
---- a/linden/indra/newview/llimview.cpp
-+++ b/linden/indra/newview/llimview.cpp
-@@ -267,8 +267,7 @@ public:
- EInstantMessage type,
- EInvitationType inv_type,
- const std::string& session_handle,
-- const std::string& notify_box,
-- const std::string& session_uri) :
-+ const std::string& notify_box) :
- mSessionID(session_id),
- mSessionName(session_name),
- mCallerID(caller_id),
-@@ -276,8 +275,7 @@ public:
- mType(type),
- mInvType(inv_type),
- mSessionHandle(session_handle),
-- mNotifyBox(notify_box),
-- mSessionURI(session_uri)
-+ mNotifyBox(notify_box)
- {};
-
- LLUUID mSessionID;
-@@ -288,7 +286,6 @@ public:
- EInvitationType mInvType;
- std::string mSessionHandle;
- std::string mNotifyBox;
-- std::string mSessionURI;
- };
-
-
-@@ -579,8 +576,7 @@ BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
-
- LLUUID LLIMMgr::addP2PSession(const std::string& name,
- const LLUUID& other_participant_id,
-- const std::string& voice_session_handle,
-- const std::string& caller_uri)
-+ const std::string& voice_session_handle)
- {
- LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
-
-@@ -588,7 +584,7 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
- if(floater)
- {
- LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel();
-- voice_channelp->setSessionHandle(voice_session_handle, caller_uri);
-+ voice_channelp->setSessionHandle(voice_session_handle);
- }
-
- return session_id;
-@@ -711,8 +707,7 @@ void LLIMMgr::inviteToSession(
- const std::string& caller_name,
- EInstantMessage type,
- EInvitationType inv_type,
-- const std::string& session_handle,
-- const std::string& session_uri)
-+ const std::string& session_handle)
- {
- //ignore invites from muted residents
- if (LLMuteList::getInstance()->isMuted(caller_id))
-@@ -754,8 +749,7 @@ void LLIMMgr::inviteToSession(
- type,
- inv_type,
- session_handle,
-- notify_box_type,
-- session_uri);
-+ notify_box_type);
-
- LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
- if (channelp && channelp->callStarted())
-@@ -930,8 +924,7 @@ void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
- invitep->mSessionID = gIMMgr->addP2PSession(
- invitep->mSessionName,
- invitep->mCallerID,
-- invitep->mSessionHandle,
-- invitep->mSessionURI );
-+ invitep->mSessionHandle);
-
- LLFloaterIMPanel* im_floater =
- gIMMgr->findFloaterBySession(
-diff --git a/linden/indra/newview/llimview.h b/linden/indra/newview/llimview.h
-index cccd6b4..cde95b5 100644
---- a/linden/indra/newview/llimview.h
-+++ b/linden/indra/newview/llimview.h
-@@ -97,8 +97,7 @@ public:
- // Creates a P2P session with the requisite handle for responding to voice calls
- LLUUID addP2PSession(const std::string& name,
- const LLUUID& other_participant_id,
-- const std::string& voice_session_handle,
-- const std::string& caller_uri = LLStringUtil::null);
-+ const std::string& voice_session_handle);
-
- // This removes the panel referenced by the uuid, and then
- // restores internal consistency. The internal pointer is not
-@@ -112,8 +111,7 @@ public:
- const std::string& caller_name,
- EInstantMessage type,
- EInvitationType inv_type,
-- const std::string& session_handle = LLStringUtil::null,
-- const std::string& session_uri = LLStringUtil::null);
-+ const std::string& session_handle = LLStringUtil::null);
-
- //Updates a given session's session IDs. Does not open,
- //create or do anything new. If the old session doesn't
-diff --git a/linden/indra/newview/llvoiceclient.cpp b/linden/indra/newview/llvoiceclient.cpp
-index 76ef87d..881beb7 100644
---- a/linden/indra/newview/llvoiceclient.cpp
-+++ b/linden/indra/newview/llvoiceclient.cpp
-@@ -1,3 +1,4 @@
-+
- /**
- * @file llvoiceclient.cpp
- * @brief Implementation of LLVoiceClient class which is the interface to the voice client process.
-@@ -62,20 +63,15 @@
- #include "llviewerwindow.h"
- #include "llviewercamera.h"
-
--#include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel
--#include "llfloaterchat.h" // for LLFloaterChat::addChat()
--
- // 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
--
-+// If we are connecting to agni AND the user's last name is "Linden", join this channel instead of looking up the sim name.
-+// If we are connecting to agni and the user's last name is NOT "Linden", disable voice.
-+#define AGNI_LINDENS_ONLY_CHANNEL "SL"
- static bool sConnectingToAgni = false;
- F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
-
-@@ -95,44 +91,6 @@ const F32 UPDATE_THROTTLE_SECONDS = 0.1f;
- const F32 LOGIN_RETRY_SECONDS = 10.0f;
- const int MAX_LOGIN_RETRIES = 12;
-
--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.
-- // Map it as follows: 0.0 -> 40, 1.0 -> 44, 2.0 -> 75
--
-- volume -= 1.0f; // offset volume to the range [-1.0 ... 1.0], with 0 at the default.
-- int scaled_volume = 44; // offset scaled_volume by its default level
-- if(volume < 0.0f)
-- scaled_volume += ((int)(volume * 4.0f)); // (44 - 40)
-- else
-- scaled_volume += ((int)(volume * 31.0f)); // (75 - 44)
--
-- return scaled_volume;
--}
--
--static int scale_speaker_volume(float volume)
--{
-- // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
-- // Map it as follows: 0.0 -> 0, 0.5 -> 62, 1.0 -> 75
--
-- volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
-- int scaled_volume = 62; // offset scaled_volume by its default level
-- if(volume < 0.0f)
-- scaled_volume += ((int)(volume * 124.0f)); // (62 - 0) * 2
-- else
-- scaled_volume += ((int)(volume * 26.0f)); // (75 - 62) * 2
--
-- return scaled_volume;
--}
--
- class LLViewerVoiceAccountProvisionResponder :
- public LLHTTPClient::Responder
- {
-@@ -146,13 +104,12 @@ public:
- {
- if ( mRetries > 0 )
- {
-- LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, retrying. status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
- if ( gVoiceClient ) gVoiceClient->requestVoiceAccountProvision(
- mRetries - 1);
- }
- else
- {
-- LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, too many retries (giving up). status = " << status << ", reason = \"" << reason << "\"" << LL_ENDL;
-+ //TODO: throw an error message?
- if ( gVoiceClient ) gVoiceClient->giveUp();
- }
- }
-@@ -161,23 +118,9 @@ public:
- {
- if ( gVoiceClient )
- {
-- std::string voice_sip_uri_hostname;
-- std::string voice_account_server_uri;
--
-- LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
--
-- if(content.has("voice_sip_uri_hostname"))
-- voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
--
-- // this key is actually misnamed -- it will be an entire URI, not just a hostname.
-- if(content.has("voice_account_server_name"))
-- voice_account_server_uri = content["voice_account_server_name"].asString();
--
- gVoiceClient->login(
- content["username"].asString(),
-- content["password"].asString(),
-- voice_sip_uri_hostname,
-- voice_account_server_uri);
-+ content["password"].asString());
- }
- }
-
-@@ -224,27 +167,21 @@ protected:
- int ignoreDepth;
-
- // Members for processing responses. The values are transient and only valid within a call to processResponse().
-- bool squelchDebugOutput;
- int returnCode;
- int statusCode;
- std::string statusString;
-- std::string requestId;
-+ std::string uuidString;
- std::string actionString;
- std::string connectorHandle;
-- std::string versionID;
- std::string accountHandle;
- std::string sessionHandle;
-- std::string sessionGroupHandle;
-- std::string alias;
-- std::string applicationString;
-+ std::string eventSessionHandle;
-
- // Members for processing events. The values are transient and only valid within a call to processResponse().
- std::string eventTypeString;
- int state;
- std::string uriString;
- bool isChannel;
-- bool incoming;
-- bool enabled;
- std::string nameString;
- std::string audioMediaString;
- std::string displayNameString;
-@@ -254,21 +191,6 @@ protected:
- bool isSpeaking;
- int volume;
- F32 energy;
-- std::string messageHeader;
-- std::string messageBody;
-- std::string notificationType;
-- bool hasText;
-- bool hasAudio;
-- bool hasVideo;
-- bool terminated;
-- std::string blockMask;
-- std::string presenceOnly;
-- std::string autoAcceptMask;
-- std::string autoAddAsBuddy;
-- int numberOfAliases;
-- std::string subscriptionHandle;
-- std::string subscriptionType;
--
-
- // Members for processing text between tags
- std::string textBuffer;
-@@ -301,6 +223,8 @@ void LLVivoxProtocolParser::reset()
- responseDepth = 0;
- ignoringTags = false;
- accumulateText = false;
-+ textBuffer.clear();
-+
- energy = 0.f;
- ignoreDepth = 0;
- isChannel = false;
-@@ -309,15 +233,10 @@ void LLVivoxProtocolParser::reset()
- isModeratorMuted = false;
- isSpeaking = false;
- participantType = 0;
-- squelchDebugOutput = false;
-- returnCode = -1;
-+ returnCode = 0;
- state = 0;
- statusCode = 0;
- volume = 0;
-- textBuffer.clear();
-- alias.clear();
-- numberOfAliases = 0;
-- applicationString.clear();
- }
-
- //virtual
-@@ -344,11 +263,33 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
- mInput.append(buf, istr.gcount());
- }
-
-+ // MBW -- XXX -- This should no longer be necessary. Or even possible.
-+ // We've read all the data out of the buffer. Make sure it doesn't accumulate.
-+// buffer->clear();
-+
- // Look for input delimiter(s) in the input buffer. If one is found, send the message to the xml parser.
- int start = 0;
- int delim;
- while((delim = mInput.find("\n\n\n", start)) != std::string::npos)
- {
-+ // Turn this on to log incoming XML
-+ if(0)
-+ {
-+ int foo = mInput.find("Set3DPosition", start);
-+ int bar = mInput.find("ParticipantPropertiesEvent", start);
-+ if(foo != std::string::npos && (foo < delim))
-+ {
-+ // This is a Set3DPosition response. Don't print it, since these are way too spammy.
-+ }
-+ else if(bar != std::string::npos && (bar < delim))
-+ {
-+ // This is a ParticipantPropertiesEvent response. Don't print it, since these are way too spammy.
-+ }
-+ else
-+ {
-+ LL_INFOS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
-+ }
-+ }
-
- // Reset internal state of the LLVivoxProtocolParser (no effect on the expat parser)
- reset();
-@@ -359,21 +300,15 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl(
- XML_SetUserData(parser, this);
- XML_Parse(parser, mInput.data() + start, delim - start, false);
-
-- // If this message isn't set to be squelched, output the raw XML received.
-- if(!squelchDebugOutput)
-- {
-- LL_DEBUGS("Voice") << "parsing: " << mInput.substr(start, delim - start) << LL_ENDL;
-- }
--
- start = delim + 3;
- }
-
- if(start != 0)
- mInput = mInput.substr(start);
-
-- LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL;
--
-- if(!gVoiceClient->mConnected)
-+ LL_DEBUGS("Voice") << "at end, mInput is: " << mInput << LL_ENDL;
-+
-+ if((!gVoiceClient)||((gVoiceClient)&&(!gVoiceClient->mConnected)))
- {
- // If voice has been disabled, we just want to close the socket. This does so.
- LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL;
-@@ -426,9 +361,9 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
-
- if (responseDepth == 0)
- {
-- isEvent = !stricmp("Event", tag);
-+ isEvent = strcmp("Event", tag) == 0;
-
-- if (!stricmp("Response", tag) || isEvent)
-+ if (strcmp("Response", tag) == 0 || isEvent)
- {
- // Grab the attributes
- while (*attr)
-@@ -436,62 +371,49 @@ void LLVivoxProtocolParser::StartTag(const char *tag, const char **attr)
- const char *key = *attr++;
- const char *value = *attr++;
-
-- if (!stricmp("requestId", key))
-+ if (strcmp("requestId", key) == 0)
- {
-- requestId = value;
-+ uuidString = value;
- }
-- else if (!stricmp("action", key))
-+ else if (strcmp("action", key) == 0)
- {
- actionString = value;
- }
-- else if (!stricmp("type", key))
-+ else if (strcmp("type", key) == 0)
- {
- eventTypeString = value;
- }
- }
- }
-- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
-+ LL_DEBUGS("Voice") << tag << " (" << responseDepth << ")" << LL_ENDL;
- }
- else
- {
- if (ignoringTags)
- {
-- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-+ LL_DEBUGS("Voice") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
- }
- else
- {
-- LL_DEBUGS("VivoxProtocolParser") << tag << " (" << responseDepth << ")" << LL_ENDL;
-+ LL_DEBUGS("Voice") << tag << " (" << responseDepth << ")" << LL_ENDL;
-
- // Ignore the InputXml stuff so we don't get confused
-- if (!stricmp("InputXml", tag))
-+ if (strcmp("InputXml", tag) == 0)
- {
- ignoringTags = true;
- ignoreDepth = responseDepth;
- accumulateText = false;
-
-- LL_DEBUGS("VivoxProtocolParser") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
-+ LL_DEBUGS("Voice") << "starting ignore, ignoreDepth is " << ignoreDepth << LL_ENDL;
- }
-- else if (!stricmp("CaptureDevices", tag))
-+ else if (strcmp("CaptureDevices", tag) == 0)
- {
- gVoiceClient->clearCaptureDevices();
- }
-- else if (!stricmp("RenderDevices", tag))
-+ else if (strcmp("RenderDevices", tag) == 0)
- {
- gVoiceClient->clearRenderDevices();
- }
-- else if (!stricmp("Buddies", tag))
-- {
-- gVoiceClient->deleteAllBuddies();
-- }
-- else if (!stricmp("BlockRules", tag))
-- {
-- gVoiceClient->deleteAllBlockRules();
-- }
-- else if (!stricmp("AutoAcceptRules", tag))
-- {
-- gVoiceClient->deleteAllAutoAcceptRules();
-- }
--
- }
- }
- responseDepth++;
-@@ -510,138 +432,90 @@ void LLVivoxProtocolParser::EndTag(const char *tag)
- {
- if (ignoreDepth == responseDepth)
- {
-- LL_DEBUGS("VivoxProtocolParser") << "end of ignore" << LL_ENDL;
-+ LL_DEBUGS("Voice") << "end of ignore" << LL_ENDL;
- ignoringTags = false;
- }
- else
- {
-- LL_DEBUGS("VivoxProtocolParser") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-+ LL_DEBUGS("Voice") << "ignoring tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
- }
- }
-
- if (!ignoringTags)
- {
-- LL_DEBUGS("VivoxProtocolParser") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-+ LL_DEBUGS("Voice") << "processing tag " << tag << " (depth = " << responseDepth << ")" << LL_ENDL;
-
- // Closing a tag. Finalize the text we've accumulated and reset
-- if (!stricmp("ReturnCode", tag))
-+ if (strcmp("ReturnCode", tag) == 0)
- returnCode = strtol(string.c_str(), NULL, 10);
-- else if (!stricmp("SessionHandle", tag))
-- sessionHandle = string;
-- else if (!stricmp("SessionGroupHandle", tag))
-- sessionGroupHandle = string;
-- else if (!stricmp("StatusCode", tag))
-+ else if (strcmp("StatusCode", tag) == 0)
- statusCode = strtol(string.c_str(), NULL, 10);
-- else if (!stricmp("StatusString", tag))
-- statusString = string;
-- else if (!stricmp("ParticipantURI", tag))
-- uriString = string;
-- else if (!stricmp("Volume", tag))
-- volume = strtol(string.c_str(), NULL, 10);
-- else if (!stricmp("Energy", tag))
-- energy = (F32)strtod(string.c_str(), NULL);
-- else if (!stricmp("IsModeratorMuted", tag))
-- isModeratorMuted = !stricmp(string.c_str(), "true");
-- else if (!stricmp("IsSpeaking", tag))
-- isSpeaking = !stricmp(string.c_str(), "true");
-- else if (!stricmp("Alias", tag))
-- alias = string;
-- else if (!stricmp("NumberOfAliases", tag))
-- numberOfAliases = strtol(string.c_str(), NULL, 10);
-- else if (!stricmp("Application", tag))
-- applicationString = string;
-- else if (!stricmp("ConnectorHandle", tag))
-+ else if (strcmp("ConnectorHandle", tag) == 0)
- connectorHandle = string;
-- else if (!stricmp("VersionID", tag))
-- versionID = string;
-- else if (!stricmp("AccountHandle", tag))
-+ else if (strcmp("AccountHandle", tag) == 0)
- accountHandle = string;
-- else if (!stricmp("State", tag))
-+ else if (strcmp("SessionHandle", tag) == 0)
-+ {
-+ if (isEvent)
-+ eventSessionHandle = string;
-+ else
-+ sessionHandle = string;
-+ }
-+ else if (strcmp("StatusString", tag) == 0)
-+ statusString = string;
-+ else if (strcmp("State", tag) == 0)
- state = strtol(string.c_str(), NULL, 10);
-- else if (!stricmp("URI", tag))
-+ else if (strcmp("URI", tag) == 0)
- uriString = string;
-- else if (!stricmp("IsChannel", tag))
-- isChannel = !stricmp(string.c_str(), "true");
-- else if (!stricmp("Incoming", tag))
-- incoming = !stricmp(string.c_str(), "true");
-- else if (!stricmp("Enabled", tag))
-- enabled = !stricmp(string.c_str(), "true");
-- else if (!stricmp("Name", tag))
-+ else if (strcmp("IsChannel", tag) == 0)
-+ isChannel = string == "true" ? true : false;
-+ else if (strcmp("Name", tag) == 0)
- nameString = string;
-- else if (!stricmp("AudioMedia", tag))
-+ else if (strcmp("AudioMedia", tag) == 0)
- audioMediaString = string;
-- else if (!stricmp("ChannelName", tag))
-+ else if (strcmp("ChannelName", tag) == 0)
- nameString = string;
-- else if (!stricmp("DisplayName", tag))
-+ else if (strcmp("ParticipantURI", tag) == 0)
-+ uriString = string;
-+ else if (strcmp("DisplayName", tag) == 0)
- displayNameString = string;
-- else if (!stricmp("AccountName", tag))
-+ else if (strcmp("AccountName", tag) == 0)
- nameString = string;
-- else if (!stricmp("ParticipantType", tag))
-+ else if (strcmp("ParticipantTyppe", tag) == 0)
- participantType = strtol(string.c_str(), NULL, 10);
-- else if (!stricmp("IsLocallyMuted", tag))
-- isLocallyMuted = !stricmp(string.c_str(), "true");
-- else if (!stricmp("MicEnergy", tag))
-+ else if (strcmp("IsLocallyMuted", tag) == 0)
-+ isLocallyMuted = string == "true" ? true : false;
-+ else if (strcmp("IsModeratorMuted", tag) == 0)
-+ isModeratorMuted = string == "true" ? true : false;
-+ else if (strcmp("IsSpeaking", tag) == 0)
-+ isSpeaking = string == "true" ? true : false;
-+ else if (strcmp("Volume", tag) == 0)
-+ volume = strtol(string.c_str(), NULL, 10);
-+ else if (strcmp("Energy", tag) == 0)
- energy = (F32)strtod(string.c_str(), NULL);
-- else if (!stricmp("ChannelName", tag))
-+ else if (strcmp("MicEnergy", tag) == 0)
-+ energy = (F32)strtod(string.c_str(), NULL);
-+ else if (strcmp("ChannelName", tag) == 0)
- nameString = string;
-- else if (!stricmp("ChannelURI", tag))
-- uriString = string;
-- else if (!stricmp("BuddyURI", tag))
-+ else if (strcmp("ChannelURI", tag) == 0)
- uriString = string;
-- else if (!stricmp("Presence", tag))
-- statusString = string;
-- else if (!stricmp("Device", tag))
-+ else if (strcmp("ChannelListResult", tag) == 0)
-+ {
-+ gVoiceClient->addChannelMapEntry(nameString, uriString);
-+ }
-+ else if (strcmp("Device", tag) == 0)
- {
- // This closing tag shouldn't clear the accumulated text.
- clearbuffer = false;
- }
-- else if (!stricmp("CaptureDevice", tag))
-+ else if (strcmp("CaptureDevice", tag) == 0)
- {
- gVoiceClient->addCaptureDevice(textBuffer);
- }
-- else if (!stricmp("RenderDevice", tag))
-+ else if (strcmp("RenderDevice", tag) == 0)
- {
- gVoiceClient->addRenderDevice(textBuffer);
- }
-- else if (!stricmp("Buddy", tag))
-- {
-- gVoiceClient->processBuddyListEntry(uriString, displayNameString);
-- }
-- else if (!stricmp("BlockRule", tag))
-- {
-- gVoiceClient->addBlockRule(blockMask, presenceOnly);
-- }
-- else if (!stricmp("BlockMask", tag))
-- blockMask = string;
-- else if (!stricmp("PresenceOnly", tag))
-- presenceOnly = string;
-- else if (!stricmp("AutoAcceptRule", tag))
-- {
-- gVoiceClient->addAutoAcceptRule(autoAcceptMask, autoAddAsBuddy);
-- }
-- else if (!stricmp("AutoAcceptMask", tag))
-- autoAcceptMask = string;
-- else if (!stricmp("AutoAddAsBuddy", tag))
-- autoAddAsBuddy = string;
-- else if (!stricmp("MessageHeader", tag))
-- messageHeader = string;
-- else if (!stricmp("MessageBody", tag))
-- messageBody = string;
-- else if (!stricmp("NotificationType", tag))
-- notificationType = string;
-- else if (!stricmp("HasText", tag))
-- hasText = !stricmp(string.c_str(), "true");
-- else if (!stricmp("HasAudio", tag))
-- hasAudio = !stricmp(string.c_str(), "true");
-- else if (!stricmp("HasVideo", tag))
-- hasVideo = !stricmp(string.c_str(), "true");
-- else if (!stricmp("Terminated", tag))
-- terminated = !stricmp(string.c_str(), "true");
-- else if (!stricmp("SubscriptionHandle", tag))
-- subscriptionHandle = string;
-- else if (!stricmp("SubscriptionType", tag))
-- subscriptionType = string;
--
-
- if(clearbuffer)
- {
-@@ -676,296 +550,147 @@ void LLVivoxProtocolParser::CharData(const char *buffer, int length)
-
- void LLVivoxProtocolParser::processResponse(std::string tag)
- {
-- LL_DEBUGS("VivoxProtocolParser") << tag << LL_ENDL;
-+ LL_DEBUGS("Voice") << tag << LL_ENDL;
-+
-+ if (!gVoiceClient)
-+ return;
-
-- // SLIM SDK: the SDK now returns a statusCode of "200" (OK) for success. This is a change vs. previous SDKs.
-- // According to Mike S., "The actual API convention is that responses with return codes of 0 are successful, regardless of the status code returned",
-- // so I believe this will give correct behavior.
--
-- if(returnCode == 0)
-- statusCode = 0;
--
- if (isEvent)
- {
-- const char *eventTypeCstr = eventTypeString.c_str();
-- if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
-+ if (eventTypeString == "LoginStateChangeEvent")
- {
-- gVoiceClient->accountLoginStateChangeEvent(accountHandle, statusCode, statusString, state);
-+ gVoiceClient->loginStateChangeEvent(accountHandle, statusCode, statusString, state);
- }
-- else if (!stricmp(eventTypeCstr, "SessionAddedEvent"))
-- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
-- sip:confctl-1408789@bhr.vivox.com
-- true
-- false
--
--
-- */
-- gVoiceClient->sessionAddedEvent(uriString, alias, sessionHandle, sessionGroupHandle, isChannel, incoming, nameString, applicationString);
-- }
-- else if (!stricmp(eventTypeCstr, "SessionRemovedEvent"))
-- {
-- gVoiceClient->sessionRemovedEvent(sessionHandle, sessionGroupHandle);
-- }
-- else if (!stricmp(eventTypeCstr, "SessionGroupAddedEvent"))
-- {
-- gVoiceClient->sessionGroupAddedEvent(sessionGroupHandle);
-- }
-- else if (!stricmp(eventTypeCstr, "MediaStreamUpdatedEvent"))
-- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
-- 200
-- OK
-- 2
-- false
--
-- */
-- gVoiceClient->mediaStreamUpdatedEvent(sessionHandle, sessionGroupHandle, statusCode, statusString, state, incoming);
-- }
-- else if (!stricmp(eventTypeCstr, "TextStreamUpdatedEvent"))
-+ else if (eventTypeString == "SessionNewEvent")
- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg1
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==1
-- true
-- 1
-- true
--
-- */
-- gVoiceClient->textStreamUpdatedEvent(sessionHandle, sessionGroupHandle, enabled, state, incoming);
-+ gVoiceClient->sessionNewEvent(accountHandle, eventSessionHandle, state, nameString, uriString);
- }
-- else if (!stricmp(eventTypeCstr, "ParticipantAddedEvent"))
-+ else if (eventTypeString == "SessionStateChangeEvent")
- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==4
-- sip:xI5auBZ60SJWIk606-1JGRQ==@bhr.vivox.com
-- xI5auBZ60SJWIk606-1JGRQ==
--
-- 0
--
-- */
-- gVoiceClient->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
-+ gVoiceClient->sessionStateChangeEvent(uriString, statusCode, statusString, eventSessionHandle, state, isChannel, nameString);
- }
-- else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
-+ else if (eventTypeString == "ParticipantStateChangeEvent")
- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg4
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==4
-- sip:xtx7YNV-3SGiG7rA1fo5Ndw==@bhr.vivox.com
-- xtx7YNV-3SGiG7rA1fo5Ndw==
--
-- */
-- gVoiceClient->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
-- }
-- else if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
-- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
-- sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com
-- false
-- true
-- 44
-- 0.0879437
--
-- */
-+ gVoiceClient->participantStateChangeEvent(uriString, statusCode, statusString, state, nameString, displayNameString, participantType);
-
-- // These happen so often that logging them is pretty useless.
-- squelchDebugOutput = true;
--
-- gVoiceClient->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
-- }
-- else if (!stricmp(eventTypeCstr, "AuxAudioPropertiesEvent"))
-- {
-- gVoiceClient->auxAudioPropertiesEvent(energy);
-- }
-- else if (!stricmp(eventTypeCstr, "BuddyPresenceEvent"))
-- {
-- gVoiceClient->buddyPresenceEvent(uriString, alias, statusString, applicationString);
-- }
-- else if (!stricmp(eventTypeCstr, "BuddyAndGroupListChangedEvent"))
-- {
-- // The buddy list was updated during parsing.
-- // Need to recheck against the friends list.
-- gVoiceClient->buddyListChanged();
-- }
-- else if (!stricmp(eventTypeCstr, "BuddyChangedEvent"))
-- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==
-- sip:x9fFHFZjOTN6OESF1DUPrZQ==@bhr.vivox.com
-- Monroe Tester
--
-- 0
-- Set
--
-- */
-- // TODO: Question: Do we need to process this at all?
-- }
-- else if (!stricmp(eventTypeCstr, "MessageEvent"))
-- {
-- gVoiceClient->messageEvent(sessionHandle, uriString, alias, messageHeader, messageBody, applicationString);
- }
-- else if (!stricmp(eventTypeCstr, "SessionNotificationEvent"))
-+ else if (eventTypeString == "ParticipantPropertiesEvent")
- {
-- gVoiceClient->sessionNotificationEvent(sessionHandle, uriString, notificationType);
-+ gVoiceClient->participantPropertiesEvent(uriString, statusCode, statusString, isLocallyMuted, isModeratorMuted, isSpeaking, volume, energy);
- }
-- else if (!stricmp(eventTypeCstr, "SubscriptionEvent"))
-+ else if (eventTypeString == "AuxAudioPropertiesEvent")
- {
-- gVoiceClient->subscriptionEvent(uriString, subscriptionHandle, alias, displayNameString, applicationString, subscriptionType);
-- }
-- else if (!stricmp(eventTypeCstr, "SessionUpdatedEvent"))
-- {
-- /*
--
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==_sg0
-- c1_m1000xFnPP04IpREWNkuw1cOXlhw==0
-- sip:confctl-9@bhd.vivox.com
-- 0
-- 50
-- 1
-- 0
-- 000
-- 0
--
-- */
-- // We don't need to process this, but we also shouldn't warn on it, since that confuses people.
-- }
-- else
-- {
-- LL_WARNS("VivoxProtocolParser") << "Unknown event type " << eventTypeString << LL_ENDL;
-+ gVoiceClient->auxAudioPropertiesEvent(energy);
- }
- }
- else
- {
-- const char *actionCstr = actionString.c_str();
-- if (!stricmp(actionCstr, "Connector.Create.1"))
-+ if (actionString == "Connector.Create.1")
- {
-- gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle, versionID);
-+ gVoiceClient->connectorCreateResponse(statusCode, statusString, connectorHandle);
- }
-- else if (!stricmp(actionCstr, "Account.Login.1"))
-+ else if (actionString == "Account.Login.1")
- {
-- gVoiceClient->loginResponse(statusCode, statusString, accountHandle, numberOfAliases);
-+ gVoiceClient->loginResponse(statusCode, statusString, accountHandle);
- }
-- else if (!stricmp(actionCstr, "Session.Create.1"))
-+ else if (actionString == "Session.Create.1")
- {
-- gVoiceClient->sessionCreateResponse(requestId, statusCode, statusString, sessionHandle);
-+ gVoiceClient->sessionCreateResponse(statusCode, statusString, sessionHandle);
- }
-- else if (!stricmp(actionCstr, "SessionGroup.AddSession.1"))
-+ else if (actionString == "Session.Connect.1")
- {
-- gVoiceClient->sessionGroupAddSessionResponse(requestId, statusCode, statusString, sessionHandle);
-+ gVoiceClient->sessionConnectResponse(statusCode, statusString);
- }
-- else if (!stricmp(actionCstr, "Session.Connect.1"))
-+ else if (actionString == "Session.Terminate.1")
- {
-- gVoiceClient->sessionConnectResponse(requestId, statusCode, statusString);
-+ gVoiceClient->sessionTerminateResponse(statusCode, statusString);
- }
-- else if (!stricmp(actionCstr, "Account.Logout.1"))
-+ else if (actionString == "Account.Logout.1")
- {
- gVoiceClient->logoutResponse(statusCode, statusString);
- }
-- else if (!stricmp(actionCstr, "Connector.InitiateShutdown.1"))
-+ else if (actionString == "Connector.InitiateShutdown.1")
- {
- gVoiceClient->connectorShutdownResponse(statusCode, statusString);
- }
-- else if (!stricmp(actionCstr, "Account.ListBlockRules.1"))
-- {
-- gVoiceClient->accountListBlockRulesResponse(statusCode, statusString);
-- }
-- else if (!stricmp(actionCstr, "Account.ListAutoAcceptRules.1"))
-- {
-- gVoiceClient->accountListAutoAcceptRulesResponse(statusCode, statusString);
-- }
-- else if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
-+ else if (actionString == "Account.ChannelGetList.1")
- {
-- // We don't need to process these, but they're so spammy we don't want to log them.
-- squelchDebugOutput = true;
-+ gVoiceClient->channelGetListResponse(statusCode, statusString);
- }
- /*
-- else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
-+ else if (actionString == "Connector.AccountCreate.1")
- {
-- gVoiceClient->channelGetListResponse(statusCode, statusString);
-+
- }
-- else if (!stricmp(actionCstr, "Connector.AccountCreate.1"))
-+ else if (actionString == "Connector.MuteLocalMic.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Connector.MuteLocalMic.1"))
-+ else if (actionString == "Connector.MuteLocalSpeaker.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Connector.MuteLocalSpeaker.1"))
-+ else if (actionString == "Connector.SetLocalMicVolume.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Connector.SetLocalMicVolume.1"))
-+ else if (actionString == "Connector.SetLocalSpeakerVolume.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Connector.SetLocalSpeakerVolume.1"))
-+ else if (actionString == "Session.ListenerSetPosition.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Session.ListenerSetPosition.1"))
-+ else if (actionString == "Session.SpeakerSetPosition.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Session.SpeakerSetPosition.1"))
-+ else if (actionString == "Session.Set3DPosition.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Session.AudioSourceSetPosition.1"))
-+ else if (actionString == "Session.AudioSourceSetPosition.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Session.GetChannelParticipants.1"))
-+ else if (actionString == "Session.GetChannelParticipants.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelCreate.1"))
-+ else if (actionString == "Account.ChannelCreate.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelUpdate.1"))
-+ else if (actionString == "Account.ChannelUpdate.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelDelete.1"))
-+ else if (actionString == "Account.ChannelDelete.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelCreateAndInvite.1"))
-+ else if (actionString == "Account.ChannelCreateAndInvite.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelFolderCreate.1"))
-+ else if (actionString == "Account.ChannelFolderCreate.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelFolderUpdate.1"))
-+ else if (actionString == "Account.ChannelFolderUpdate.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelFolderDelete.1"))
-+ else if (actionString == "Account.ChannelFolderDelete.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelAddModerator.1"))
-+ else if (actionString == "Account.ChannelAddModerator.1")
- {
-
- }
-- else if (!stricmp(actionCstr, "Account.ChannelDeleteModerator.1"))
-+ else if (actionString == "Account.ChannelDeleteModerator.1")
- {
-
- }
-@@ -979,18 +704,9 @@ class LLVoiceClientMuteListObserver : public LLMuteListObserver
- {
- /* virtual */ void onChange() { gVoiceClient->muteListChanged();}
- };
--
--class LLVoiceClientFriendsObserver : public LLFriendObserver
--{
--public:
-- /* virtual */ void changed(U32 mask) { gVoiceClient->updateFriends(mask);}
--};
--
- static LLVoiceClientMuteListObserver mutelist_listener;
- static bool sMuteListListener_listening = false;
-
--static LLVoiceClientFriendsObserver *friendslist_listener = NULL;
--
- ///////////////////////////////////////////////////////////////////////////////////////////////
-
- class LLVoiceClientCapResponder : public LLHTTPClient::Responder
-@@ -1014,8 +730,11 @@ void LLVoiceClientCapResponder::error(U32 status, const std::string& reason)
- void LLVoiceClientCapResponder::result(const LLSD& content)
- {
- LLSD::map_const_iterator iter;
--
-- LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
-+ for(iter = content.beginMap(); iter != content.endMap(); ++iter)
-+ {
-+ LL_DEBUGS("Voice") << "LLVoiceClientCapResponder::result got "
-+ << iter->first << LL_ENDL;
-+ }
-
- if ( content.has("voice_credentials") )
- {
-@@ -1101,26 +820,26 @@ LLVoiceClient::LLVoiceClient()
- mUserPTTState = false;
- mMuteMic = false;
- mSessionTerminateRequested = false;
-- mRelogRequested = false;
- mCommandCookie = 0;
-+ mNonSpatialChannel = false;
-+ mNextSessionSpatial = true;
-+ mNextSessionNoReconnect = false;
-+ mSessionP2P = false;
- mCurrentParcelLocalID = 0;
- mLoginRetryCount = 0;
-+ mVivoxErrorStatusCode = 0;
-
-+ mNextSessionResetOnClose = false;
-+ mSessionResetOnClose = false;
- mSpeakerVolume = 0;
- mMicVolume = 0;
-
-- mAudioSession = NULL;
-- mAudioSessionChanged = false;
--
- // Initial dirty state
- mSpatialCoordsDirty = false;
- mPTTDirty = true;
-- mFriendsListDirty = true;
-+ mVolumeDirty = true;
- mSpeakerVolumeDirty = true;
- mMicVolumeDirty = true;
-- mBuddyListMapPopulated = false;
-- mBlockRulesListReceived = false;
-- mAutoAcceptRulesListReceived = false;
- mCaptureDeviceDirty = false;
- mRenderDeviceDirty = false;
-
-@@ -1141,12 +860,14 @@ LLVoiceClient::LLVoiceClient()
- // gMuteListp isn't set up at this point, so we defer this until later.
- // gMuteListp->addObserver(&mutelist_listener);
-
-+ mParticipantMapChanged = false;
-+
- // stash the pump for later use
- // This now happens when init() is called instead.
- mPump = NULL;
-
- #if LL_DARWIN || LL_LINUX
-- // HACK: THIS DOES NOT BELONG HERE
-+ // MBW -- XXX -- THIS DOES NOT BELONG HERE
- // When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
- // This should cause us to ignore SIGPIPE and handle the error through proper channels.
- // This should really be set up elsewhere. Where should it go?
-@@ -1182,10 +903,8 @@ void LLVoiceClient::terminate()
- {
- if(gVoiceClient)
- {
--// gVoiceClient->leaveAudioSession();
-+ gVoiceClient->sessionTerminateSendMessage();
- gVoiceClient->logout();
-- // As of SDK version 4885, this should no longer be necessary. It will linger after the socket close if it needs to.
-- // ms_sleep(2000);
- gVoiceClient->connectorShutdown();
- gVoiceClient->closeSocket(); // Need to do this now -- bad things happen if the destructor does it later.
-
-@@ -1210,13 +929,13 @@ void LLVoiceClient::updateSettings()
- setPTTKey(keyString);
- setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
- setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
-+ std::string serverName = gSavedSettings.getString("VivoxDebugServerName");
-+ setVivoxDebugServerName(serverName);
-
- std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
- setCaptureDevice(inputDevice);
- std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
- setRenderDevice(outputDevice);
-- F32 mic_level = gSavedSettings.getF32("AudioLevelMic");
-- setMicGain(mic_level);
- setLipSyncEnabled(gSavedSettings.getBOOL("LipSyncEnabled"));
- }
-
-@@ -1232,10 +951,9 @@ bool LLVoiceClient::writeString(const std::string &str)
- apr_size_t size = (apr_size_t)str.size();
- apr_size_t written = size;
-
-- //MARK: Turn this on to log outgoing XML
--// LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
-+ LL_DEBUGS("Voice") << "sending: " << str << LL_ENDL;
-
-- // check return code - sockets will fail (broken, etc.)
-+ // MBW -- XXX -- check return code - sockets will fail (broken, etc.)
- err = apr_socket_send(
- mSocket->getSocket(),
- (const char*)str.data(),
-@@ -1246,7 +964,7 @@ bool LLVoiceClient::writeString(const std::string &str)
- // Success.
- result = true;
- }
-- // TODO: handle partial writes (written is number of bytes written)
-+ // MBW -- XXX -- handle partial writes (written is number of bytes written)
- // Need to set socket to non-blocking before this will work.
- // else if(APR_STATUS_IS_EAGAIN(err))
- // {
-@@ -1270,7 +988,7 @@ bool LLVoiceClient::writeString(const std::string &str)
- void LLVoiceClient::connectorCreate()
- {
- std::ostringstream stream;
-- std::string logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-+ std::string logpath;
- std::string loglevel = "0";
-
- // Transition to stateConnectorStarted when the connector handle comes back.
-@@ -1282,20 +1000,20 @@ void LLVoiceClient::connectorCreate()
- {
- LL_DEBUGS("Voice") << "creating connector with logging enabled" << LL_ENDL;
- loglevel = "10";
-+ logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
- }
-
- stream
- << ""
- << "V2 SDK"
-- << "" << mVoiceAccountServerURI << ""
-- << "Normal"
-+ << "" << mAccountServerURI << ""
- << ""
-+ << "false"
- << "" << logpath << ""
- << "Connector"
- << ".log"
- << "" << loglevel << ""
- << ""
-- << "SecondLifeViewer.1"
- << "\n\n\n";
-
- writeString(stream.str());
-@@ -1333,6 +1051,20 @@ void LLVoiceClient::userAuthorized(const std::string& firstName, const std::stri
-
- sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid();
-
-+ // MBW -- XXX -- Enable this when the bhd.vivox.com server gets a real ssl cert.
-+ if(sConnectingToAgni)
-+ {
-+ // Use the release account server
-+ mAccountServerName = "bhr.vivox.com";
-+ mAccountServerURI = "https://www." + mAccountServerName + "/api2/";
-+ }
-+ else
-+ {
-+ // Use the development account server
-+ mAccountServerName = gSavedSettings.getString("VivoxDebugServerName");
-+ mAccountServerURI = "https://www." + mAccountServerName + "/api2/";
-+ }
-+
- mAccountName = nameFromID(agentID);
- }
-
-@@ -1354,69 +1086,24 @@ void LLVoiceClient::requestVoiceAccountProvision(S32 retries)
- }
-
- void LLVoiceClient::login(
-- const std::string& account_name,
-- const std::string& password,
-- const std::string& voice_sip_uri_hostname,
-- const std::string& voice_account_server_uri)
-+ const std::string& accountName,
-+ const std::string &password)
- {
-- mVoiceSIPURIHostName = voice_sip_uri_hostname;
-- mVoiceAccountServerURI = voice_account_server_uri;
--
-- if(!mAccountHandle.empty())
-+ if((getState() >= stateLoggingIn) && (getState() < stateLoggedOut))
- {
-- // Already logged in.
-- LL_WARNS("Voice") << "Called while already logged in." << LL_ENDL;
--
-- // Don't process another login.
-- return;
-+ // Already logged in. This is an internal error.
-+ LL_ERRS("Voice") << "Can't login again. Called from wrong state." << LL_ENDL;
- }
-- else if ( account_name != mAccountName )
-+ else if ( accountName != mAccountName )
- {
- //TODO: error?
-- LL_WARNS("Voice") << "Wrong account name! " << account_name
-+ LL_WARNS("Voice") << "Wrong account name! " << accountName
- << " instead of " << mAccountName << LL_ENDL;
- }
- else
- {
- mAccountPassword = password;
- }
--
-- std::string debugSIPURIHostName = gSavedSettings.getString("VivoxDebugSIPURIHostName");
--
-- if( !debugSIPURIHostName.empty() )
-- {
-- mVoiceSIPURIHostName = debugSIPURIHostName;
-- }
--
-- if( mVoiceSIPURIHostName.empty() )
-- {
-- // we have an empty account server name
-- // so we fall back to hardcoded defaults
--
-- if(sConnectingToAgni)
-- {
-- // Use the release account server
-- mVoiceSIPURIHostName = "bhr.vivox.com";
-- }
-- else
-- {
-- // Use the development account server
-- mVoiceSIPURIHostName = "bhd.vivox.com";
-- }
-- }
--
-- std::string debugAccountServerURI = gSavedSettings.getString("VivoxDebugVoiceAccountServerURI");
--
-- if( !debugAccountServerURI.empty() )
-- {
-- mVoiceAccountServerURI = debugAccountServerURI;
-- }
--
-- if( mVoiceAccountServerURI.empty() )
-- {
-- // If the account server URI isn't specified, construct it from the SIP URI hostname
-- mVoiceAccountServerURI = "https://www." + mVoiceSIPURIHostName + "/api2/";
-- }
- }
-
- void LLVoiceClient::idle(void* user_data)
-@@ -1434,16 +1121,11 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
-
- switch(inState)
- {
-- CASE(stateDisableCleanup);
- CASE(stateDisabled);
- CASE(stateStart);
- CASE(stateDaemonLaunched);
- CASE(stateConnecting);
-- CASE(stateConnected);
- CASE(stateIdle);
-- CASE(stateMicTuningStart);
-- CASE(stateMicTuningRunning);
-- CASE(stateMicTuningStop);
- CASE(stateConnectorStart);
- CASE(stateConnectorStarting);
- CASE(stateConnectorStarted);
-@@ -1452,8 +1134,12 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
- CASE(stateNeedsLogin);
- CASE(stateLoggingIn);
- CASE(stateLoggedIn);
-- CASE(stateCreatingSessionGroup);
- CASE(stateNoChannel);
-+ CASE(stateMicTuningStart);
-+ CASE(stateMicTuningRunning);
-+ CASE(stateMicTuningStop);
-+ CASE(stateSessionCreate);
-+ CASE(stateSessionConnect);
- CASE(stateJoiningSession);
- CASE(stateSessionJoined);
- CASE(stateRunning);
-@@ -1470,6 +1156,7 @@ std::string LLVoiceClient::state2string(LLVoiceClient::state inState)
- CASE(stateJoinSessionFailed);
- CASE(stateJoinSessionFailedWaiting);
- CASE(stateJail);
-+ CASE(stateMicTuningNoLogin);
- }
-
- #undef CASE
-@@ -1491,7 +1178,6 @@ std::string LLVoiceClientStatusObserver::status2string(LLVoiceClientStatusObserv
- CASE(STATUS_JOINING);
- CASE(STATUS_JOINED);
- CASE(STATUS_LEFT_CHANNEL);
-- CASE(STATUS_VOICE_DISABLED);
- CASE(BEGIN_ERROR_STATUS);
- CASE(ERROR_CHANNEL_FULL);
- CASE(ERROR_CHANNEL_LOCKED);
-@@ -1525,13 +1211,9 @@ void LLVoiceClient::stateMachine()
- {
- updatePosition();
- }
-- else if(mTuningMode)
-- {
-- // Tuning mode is special -- it needs to launch SLVoice even if voice is disabled.
-- }
- else
- {
-- if((getState() != stateDisabled) && (getState() != stateDisableCleanup))
-+ if(getState() != stateDisabled)
- {
- // User turned off voice support. Send the cleanup messages, close the socket, and reset.
- if(!mConnected)
-@@ -1541,10 +1223,13 @@ void LLVoiceClient::stateMachine()
- killGateway();
- }
-
-+ sessionTerminateSendMessage();
- logout();
- connectorShutdown();
--
-- setState(stateDisableCleanup);
-+ closeSocket();
-+ removeAllParticipants();
-+
-+ setState(stateDisabled);
- }
- }
-
-@@ -1559,7 +1244,7 @@ void LLVoiceClient::stateMachine()
- std::string regionName = region->getName();
- std::string capURI = region->getCapability("ParcelVoiceInfoRequest");
-
--// LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL;
-+ LL_DEBUGS("Voice") << "Region name = \"" << regionName <<"\", " << "parcel local ID = " << parcelLocalID << LL_ENDL;
-
- // The region name starts out empty and gets filled in later.
- // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
-@@ -1580,30 +1265,13 @@ void LLVoiceClient::stateMachine()
-
- switch(getState())
- {
-- //MARK: stateDisableCleanup
-- case stateDisableCleanup:
-- // Clean up and reset everything.
-- closeSocket();
-- deleteAllSessions();
-- deleteAllBuddies();
--
-- mConnectorHandle.clear();
-- mAccountHandle.clear();
-- mAccountPassword.clear();
-- mVoiceAccountServerURI.clear();
--
-- setState(stateDisabled);
-- break;
--
-- //MARK: stateDisabled
- case stateDisabled:
-- if(mTuningMode || (mVoiceEnabled && !mAccountName.empty()))
-+ if(mVoiceEnabled && (!mAccountName.empty() || mTuningMode))
- {
- setState(stateStart);
- }
- break;
-
-- //MARK: stateStart
- case stateStart:
- if(gSavedSettings.getBOOL("CmdLineDisableVoice"))
- {
-@@ -1634,9 +1302,7 @@ void LLVoiceClient::stateMachine()
- if(!LLFile::stat(exe_path, &s))
- {
- // vivox executable exists. Build the command line and launch the daemon.
-- // SLIM SDK: these arguments are no longer necessary.
--// std::string args = " -p tcp -h -c";
-- std::string args;
-+ std::string args = " -p tcp -h -c";
- std::string cmd;
- std::string loglevel = gSavedSettings.getString("VivoxDebugLevel");
-
-@@ -1721,15 +1387,14 @@ void LLVoiceClient::stateMachine()
- }
- else
- {
-- LL_INFOS("Voice") << exe_path << " not found." << LL_ENDL;
-+ LL_INFOS("Voice") << exe_path << "not found." << LL_ENDL;
- }
- }
- else
- {
-- // SLIM SDK: port changed from 44124 to 44125.
- // We can connect to a client gateway running on another host. This is useful for testing.
- // To do this, launch the gateway on a nearby host like this:
-- // vivox-gw.exe -p tcp -i 0.0.0.0:44125
-+ // vivox-gw.exe -p tcp -i 0.0.0.0:44124
- // and put that host's IP address here.
- mDaemonHost = LLHost(gSavedSettings.getString("VoiceHost"), gSavedSettings.getU32("VoicePort"));
- }
-@@ -1741,23 +1406,17 @@ void LLVoiceClient::stateMachine()
-
- // Dirty the states we'll need to sync with the daemon when it comes up.
- mPTTDirty = true;
-- mMicVolumeDirty = true;
- mSpeakerVolumeDirty = true;
-- mSpeakerMuteDirty = true;
- // These only need to be set if they're not default (i.e. empty string).
- mCaptureDeviceDirty = !mCaptureDevice.empty();
- mRenderDeviceDirty = !mRenderDevice.empty();
--
-- mMainSessionGroupHandle.clear();
- }
- break;
--
-- //MARK: stateDaemonLaunched
-+
- case stateDaemonLaunched:
-+ LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
- if(mUpdateTimer.hasExpired())
- {
-- LL_DEBUGS("Voice") << "Connecting to vivox daemon" << LL_ENDL;
--
- mUpdateTimer.setTimerExpirySec(CONNECT_THROTTLE_SECONDS);
-
- if(!mSocket)
-@@ -1778,7 +1437,6 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateConnecting
- case stateConnecting:
- // Can't do this until we have the pump available.
- if(mPump)
-@@ -1796,34 +1454,48 @@ void LLVoiceClient::stateMachine()
-
- mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS);
-
-- setState(stateConnected);
-+ setState(stateIdle);
- }
-
- break;
-
-- //MARK: stateConnected
-- case stateConnected:
-+ case stateIdle:
- // Initial devices query
- getCaptureDevicesSendMessage();
- getRenderDevicesSendMessage();
-
- mLoginRetryCount = 0;
--
-- setState(stateIdle);
-+
-+ setState(stateConnectorStart);
-+
- break;
--
-- //MARK: stateIdle
-- case stateIdle:
-- // This is the idle state where we're connected to the daemon but haven't set up a connector yet.
-- if(mTuningMode)
-+
-+ case stateConnectorStart:
-+ if(!mVoiceEnabled)
- {
-- mTuningExitState = stateIdle;
-+ // We were never logged in. This will shut down the connector.
-+ setState(stateLoggedOut);
-+ }
-+ else if(!mAccountServerURI.empty())
-+ {
-+ connectorCreate();
-+ }
-+ else if(mTuningMode)
-+ {
-+ mTuningExitState = stateConnectorStart;
- setState(stateMicTuningStart);
- }
-- else if(!mVoiceEnabled)
-+ break;
-+
-+ case stateConnectorStarting: // waiting for connector handle
-+ // connectorCreateResponse() will transition from here to stateConnectorStarted.
-+ break;
-+
-+ case stateConnectorStarted: // connector handle received
-+ if(!mVoiceEnabled)
- {
-- // We never started up the connector. This will shut down the daemon.
-- setState(stateConnectorStopped);
-+ // We were never logged in. This will shut down the connector.
-+ setState(stateLoggedOut);
- }
- else if(!mAccountName.empty())
- {
-@@ -1837,13 +1509,12 @@ void LLVoiceClient::stateMachine()
- {
- requestVoiceAccountProvision();
- }
-- setState(stateConnectorStart);
-+ setState(stateNeedsLogin);
- }
- }
- }
- break;
--
-- //MARK: stateMicTuningStart
-+
- case stateMicTuningStart:
- if(mUpdateTimer.hasExpired())
- {
-@@ -1851,9 +1522,19 @@ void LLVoiceClient::stateMachine()
- {
- // These can't be changed while in tuning mode. Set them before starting.
- std::ostringstream stream;
--
-- buildSetCaptureDevice(stream);
-- buildSetRenderDevice(stream);
-+
-+ if(mCaptureDeviceDirty)
-+ {
-+ buildSetCaptureDevice(stream);
-+ }
-+
-+ if(mRenderDeviceDirty)
-+ {
-+ buildSetRenderDevice(stream);
-+ }
-+
-+ mCaptureDeviceDirty = false;
-+ mRenderDeviceDirty = false;
-
- if(!stream.str().empty())
- {
-@@ -1875,9 +1556,8 @@ void LLVoiceClient::stateMachine()
-
- break;
-
-- //MARK: stateMicTuningRunning
- case stateMicTuningRunning:
-- if(!mTuningMode || mCaptureDeviceDirty || mRenderDeviceDirty)
-+ if(!mTuningMode || !mVoiceEnabled || mSessionTerminateRequested || mCaptureDeviceDirty || mRenderDeviceDirty)
- {
- // All of these conditions make us leave tuning mode.
- setState(stateMicTuningStop);
-@@ -1917,7 +1597,6 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateMicTuningStop
- case stateMicTuningStop:
- {
- // transition out of mic tuning
-@@ -1931,40 +1610,7 @@ void LLVoiceClient::stateMachine()
-
- }
- break;
--
-- //MARK: stateConnectorStart
-- case stateConnectorStart:
-- if(!mVoiceEnabled)
-- {
-- // We were never logged in. This will shut down the connector.
-- setState(stateLoggedOut);
-- }
-- else if(!mVoiceAccountServerURI.empty())
-- {
-- connectorCreate();
-- }
-- break;
--
-- //MARK: stateConnectorStarting
-- case stateConnectorStarting: // waiting for connector handle
-- // connectorCreateResponse() will transition from here to stateConnectorStarted.
-- break;
--
-- //MARK: stateConnectorStarted
-- case stateConnectorStarted: // connector handle received
-- if(!mVoiceEnabled)
-- {
-- // We were never logged in. This will shut down the connector.
-- setState(stateLoggedOut);
-- }
-- else
-- {
-- // The connector is started. Send a login message.
-- setState(stateNeedsLogin);
-- }
-- break;
--
-- //MARK: stateLoginRetry
-+
- case stateLoginRetry:
- if(mLoginRetryCount == 0)
- {
-@@ -1988,7 +1634,6 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateLoginRetryWait
- case stateLoginRetryWait:
- if(mUpdateTimer.hasExpired())
- {
-@@ -1996,7 +1641,6 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateNeedsLogin
- case stateNeedsLogin:
- if(!mAccountPassword.empty())
- {
-@@ -2005,22 +1649,16 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateLoggingIn
- case stateLoggingIn: // waiting for account handle
- // loginResponse() will transition from here to stateLoggedIn.
- break;
-
-- //MARK: stateLoggedIn
- case stateLoggedIn: // account handle received
-+ // Initial kick-off of channel lookup logic
-+ parcelChanged();
-
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LOGGED_IN);
-
-- // request the current set of block rules (we'll need them when updating the friends list)
-- accountListBlockRulesSendMessage();
--
-- // request the current set of auto-accept rules
-- accountListAutoAcceptRulesSendMessage();
--
- // Set up the mute list observer if it hasn't been set up already.
- if((!sMuteListListener_listening))
- {
-@@ -2028,67 +1666,13 @@ void LLVoiceClient::stateMachine()
- sMuteListListener_listening = true;
- }
-
-- // Set up the friends list observer if it hasn't been set up already.
-- if(friendslist_listener == NULL)
-- {
-- friendslist_listener = new LLVoiceClientFriendsObserver;
-- LLAvatarTracker::instance().addObserver(friendslist_listener);
-- }
--
-- // Set the initial state of mic mute, local speaker volume, etc.
-- {
-- std::ostringstream stream;
--
-- buildLocalAudioUpdates(stream);
--
-- if(!stream.str().empty())
-- {
-- writeString(stream.str());
-- }
-- }
--
--#if USE_SESSION_GROUPS
-- // create the main session group
-- sessionGroupCreateSendMessage();
--
-- setState(stateCreatingSessionGroup);
--#else
-- // Not using session groups -- skip the stateCreatingSessionGroup state.
- setState(stateNoChannel);
--
-- // Initial kick-off of channel lookup logic
-- parcelChanged();
--#endif
-- break;
--
-- //MARK: stateCreatingSessionGroup
-- case stateCreatingSessionGroup:
-- if(mSessionTerminateRequested || !mVoiceEnabled)
-- {
-- // TODO: Question: is this the right way out of this state
-- setState(stateSessionTerminated);
-- }
-- else if(!mMainSessionGroupHandle.empty())
-- {
-- setState(stateNoChannel);
--
-- // Start looped recording (needed for "panic button" anti-griefing tool)
-- recordingLoopStart();
--
-- // Initial kick-off of channel lookup logic
-- parcelChanged();
-- }
- break;
-
-- //MARK: stateNoChannel
- case stateNoChannel:
-- // Do this here as well as inside sendPositionalUpdate().
-- // Otherwise, if you log in but don't join a proximal channel (such as when your login location has voice disabled), your friends list won't sync.
-- sendFriendsListUpdates();
--
- if(mSessionTerminateRequested || !mVoiceEnabled)
- {
-- // TODO: Question: Is this the right way out of this state?
-+ // MBW -- XXX -- Is this the right way out of this state?
- setState(stateSessionTerminated);
- }
- else if(mTuningMode)
-@@ -2096,49 +1680,30 @@ void LLVoiceClient::stateMachine()
- mTuningExitState = stateNoChannel;
- setState(stateMicTuningStart);
- }
-- else if(sessionNeedsRelog(mNextAudioSession))
-+ else if(!mNextSessionHandle.empty())
- {
-- requestRelog();
-- setState(stateSessionTerminated);
-+ setState(stateSessionConnect);
- }
-- else if(mNextAudioSession)
-- {
-- sessionState *oldSession = mAudioSession;
--
-- mAudioSession = mNextAudioSession;
-- if(!mAudioSession->mReconnect)
-- {
-- mNextAudioSession = NULL;
-- }
--
-- // The old session may now need to be deleted.
-- reapSession(oldSession);
--
-- if(!mAudioSession->mHandle.empty())
-- {
-- // Connect to a session by session handle
--
-- sessionMediaConnectSendMessage(mAudioSession);
-- }
-- else
-- {
-- // Connect to a session by URI
-- sessionCreateSendMessage(mAudioSession, true, false);
-- }
--
-- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
-- setState(stateJoiningSession);
-- }
-- else if(!mSpatialSessionURI.empty())
-+ else if(!mNextSessionURI.empty())
- {
-- // If we're not headed elsewhere and have a spatial URI, return to spatial.
-- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
-+ setState(stateSessionCreate);
- }
- break;
-
-- //MARK: stateJoiningSession
-+ case stateSessionCreate:
-+ sessionCreateSendMessage();
-+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
-+ setState(stateJoiningSession);
-+ break;
-+
-+ case stateSessionConnect:
-+ sessionConnectSendMessage();
-+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
-+ setState(stateJoiningSession);
-+ break;
-+
- case stateJoiningSession: // waiting for session handle
-- // joinedAudioSession() will transition from here to stateSessionJoined.
-+ // sessionCreateResponse() will transition from here to stateSessionJoined.
- if(!mVoiceEnabled)
- {
- // User bailed out during connect -- jump straight to teardown.
-@@ -2146,27 +1711,30 @@ void LLVoiceClient::stateMachine()
- }
- else if(mSessionTerminateRequested)
- {
-- if(mAudioSession && !mAudioSession->mHandle.empty())
-+ if(!mSessionHandle.empty())
- {
- // Only allow direct exits from this state in p2p calls (for cancelling an invite).
- // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
-- if(mAudioSession->mIsP2P)
-+ if(mSessionP2P)
- {
-- sessionMediaDisconnectSendMessage(mAudioSession);
-+ sessionTerminateSendMessage();
- setState(stateSessionTerminated);
- }
- }
- }
- break;
-
-- //MARK: stateSessionJoined
- case stateSessionJoined: // session handle received
-- // It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
-- // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
-- // For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
-+ // MBW -- XXX -- It appears that I need to wait for BOTH the Session.Create response and the SessionStateChangeEvent with state 4
-+ // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
-+ // For now, the Session.Create response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
- // This is a cheap way to make sure both have happened before proceeding.
-- if(mAudioSession && mAudioSession->mVoiceEnabled)
-+ if(!mSessionHandle.empty())
- {
-+ // Events that need to happen when a session is joined could go here.
-+ // Maybe send initial spatial data?
-+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
-+
- // Dirty state that may need to be sync'ed with the daemon.
- mPTTDirty = true;
- mSpeakerVolumeDirty = true;
-@@ -2177,11 +1745,6 @@ void LLVoiceClient::stateMachine()
- // Start the throttle timer
- mUpdateTimer.start();
- mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
--
-- // Events that need to happen when a session is joined could go here.
-- // Maybe send initial spatial data?
-- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINED);
--
- }
- else if(!mVoiceEnabled)
- {
-@@ -2192,20 +1755,21 @@ void LLVoiceClient::stateMachine()
- {
- // Only allow direct exits from this state in p2p calls (for cancelling an invite).
- // Terminating a half-connected session on other types of calls seems to break something in the vivox gateway.
-- if(mAudioSession && mAudioSession->mIsP2P)
-+ if(mSessionP2P)
- {
-- sessionMediaDisconnectSendMessage(mAudioSession);
-+ sessionTerminateSendMessage();
- setState(stateSessionTerminated);
- }
- }
- break;
-
-- //MARK: stateRunning
- case stateRunning: // steady state
-+ // sessionTerminateSendMessage() will transition from here to stateLeavingSession
-+
- // Disabling voice or disconnect requested.
- if(!mVoiceEnabled || mSessionTerminateRequested)
- {
-- leaveAudioSession();
-+ sessionTerminateSendMessage();
- }
- else
- {
-@@ -2238,7 +1802,7 @@ void LLVoiceClient::stateMachine()
- }
- }
-
-- if(!inSpatialChannel())
-+ if(mNonSpatialChannel)
- {
- // When in a non-spatial channel, never send positional updates.
- mSpatialCoordsDirty = false;
-@@ -2251,7 +1815,7 @@ void LLVoiceClient::stateMachine()
-
- // Send an update if the ptt state has changed (which shouldn't be able to happen that often -- the user can only click so fast)
- // or every 10hz, whichever is sooner.
-- if((mAudioSession && mAudioSession->mVolumeDirty) || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
-+ if(mVolumeDirty || mPTTDirty || mSpeakerVolumeDirty || mUpdateTimer.hasExpired())
- {
- mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
- sendPositionalUpdate();
-@@ -2259,38 +1823,25 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateLeavingSession
- case stateLeavingSession: // waiting for terminate session response
- // The handler for the Session.Terminate response will transition from here to stateSessionTerminated.
- break;
-
-- //MARK: stateSessionTerminated
- case stateSessionTerminated:
-+ // Always reset the terminate request flag when we get here.
-+ mSessionTerminateRequested = false;
-
-- // Must do this first, since it uses mAudioSession.
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL);
--
-- if(mAudioSession)
-- {
-- sessionState *oldSession = mAudioSession;
-
-- mAudioSession = NULL;
-- // We just notified status observers about this change. Don't do it again.
-- mAudioSessionChanged = false;
--
-- // The old session may now need to be deleted.
-- reapSession(oldSession);
-- }
-- else
-+ if(mVoiceEnabled)
- {
-- LL_WARNS("Voice") << "stateSessionTerminated with NULL mAudioSession" << LL_ENDL;
-- }
--
-- // Always reset the terminate request flag when we get here.
-- mSessionTerminateRequested = false;
--
-- if(mVoiceEnabled && !mRelogRequested)
-- {
-+ // SPECIAL CASE: if going back to spatial but in a parcel with an empty URI, transfer the non-spatial flag now.
-+ // This fixes the case where you come out of a group chat in a parcel with voice disabled, and get stuck unable to rejoin spatial chat thereafter.
-+ if(mNextSessionSpatial && mNextSessionURI.empty())
-+ {
-+ mNonSpatialChannel = !mNextSessionSpatial;
-+ }
-+
- // Just leaving a channel, go back to stateNoChannel (the "logged in but have no channel" state).
- setState(stateNoChannel);
- }
-@@ -2298,67 +1849,49 @@ void LLVoiceClient::stateMachine()
- {
- // Shutting down voice, continue with disconnecting.
- logout();
--
-- // The state machine will take it from here
-- mRelogRequested = false;
- }
-
- break;
-
-- //MARK: stateLoggingOut
- case stateLoggingOut: // waiting for logout response
- // The handler for the Account.Logout response will transition from here to stateLoggedOut.
- break;
-- //MARK: stateLoggedOut
- case stateLoggedOut: // logout response received
- // shut down the connector
- connectorShutdown();
- break;
-
-- //MARK: stateConnectorStopping
- case stateConnectorStopping: // waiting for connector stop
- // The handler for the Connector.InitiateShutdown response will transition from here to stateConnectorStopped.
- break;
-
-- //MARK: stateConnectorStopped
- case stateConnectorStopped: // connector stop received
-- setState(stateDisableCleanup);
-+ // Clean up and reset everything.
-+ closeSocket();
-+ removeAllParticipants();
-+ setState(stateDisabled);
- break;
-
-- //MARK: stateConnectorFailed
- case stateConnectorFailed:
- setState(stateConnectorFailedWaiting);
- break;
-- //MARK: stateConnectorFailedWaiting
- case stateConnectorFailedWaiting:
- break;
-
-- //MARK: stateLoginFailed
- case stateLoginFailed:
- setState(stateLoginFailedWaiting);
- break;
-- //MARK: stateLoginFailedWaiting
- case stateLoginFailedWaiting:
- // No way to recover from these. Yet.
- break;
-
-- //MARK: stateJoinSessionFailed
- case stateJoinSessionFailed:
- // Transition to error state. Send out any notifications here.
-- if(mAudioSession)
-- {
-- LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mAudioSession->mErrorStatusCode << "): " << mAudioSession->mErrorStatusString << LL_ENDL;
-- }
-- else
-- {
-- LL_WARNS("Voice") << "stateJoinSessionFailed with no current session" << LL_ENDL;
-- }
--
-+ LL_WARNS("Voice") << "stateJoinSessionFailed: (" << mVivoxErrorStatusCode << "): " << mVivoxErrorStatusString << LL_ENDL;
- notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
- setState(stateJoinSessionFailedWaiting);
- break;
-
-- //MARK: stateJoinSessionFailedWaiting
- case stateJoinSessionFailedWaiting:
- // Joining a channel failed, either due to a failed channel name -> sip url lookup or an error from the join message.
- // Region crossings may leave this state and try the join again.
-@@ -2368,24 +1901,22 @@ void LLVoiceClient::stateMachine()
- }
- break;
-
-- //MARK: stateJail
- case stateJail:
- // We have given up. Do nothing.
- break;
-
-+ case stateMicTuningNoLogin:
-+ // *TODO: Implement me.
-+ LL_WARNS("Voice") << "stateMicTuningNoLogin not handled" << LL_ENDL;
-+ break;
- }
--
-- if(mAudioSession && mAudioSession->mParticipantsChanged)
-- {
-- mAudioSession->mParticipantsChanged = false;
-- mAudioSessionChanged = true;
-- }
--
-- if(mAudioSessionChanged)
-+
-+ if(mParticipantMapChanged)
- {
-- mAudioSessionChanged = false;
-- notifyParticipantObservers();
-+ mParticipantMapChanged = false;
-+ notifyObservers();
- }
-+
- }
-
- void LLVoiceClient::closeSocket(void)
-@@ -2403,9 +1934,6 @@ void LLVoiceClient::loginSendMessage()
- << "" << mAccountName << ""
- << "" << mAccountPassword << ""
- << "VerifyAnswer"
-- << "true"
-- << "Application"
-- << "5"
- << "\n\n\n";
-
- writeString(stream.str());
-@@ -2413,10 +1941,7 @@ void LLVoiceClient::loginSendMessage()
-
- void LLVoiceClient::logout()
- {
-- // Ensure that we'll re-request provisioning before logging in again
-- mAccountPassword.clear();
-- mVoiceAccountServerURI.clear();
--
-+ mAccountPassword = "";
- setState(stateLoggingOut);
- logoutSendMessage();
- }
-@@ -2438,164 +1963,78 @@ void LLVoiceClient::logoutSendMessage()
- }
- }
-
--void LLVoiceClient::accountListBlockRulesSendMessage()
-+void LLVoiceClient::channelGetListSendMessage()
- {
-- if(!mAccountHandle.empty())
-- {
-- std::ostringstream stream;
--
-- LL_DEBUGS("Voice") << "requesting block rules" << LL_ENDL;
--
-- stream
-- << ""
-- << "" << mAccountHandle << ""
-- << ""
-- << "\n\n\n";
--
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::accountListAutoAcceptRulesSendMessage()
--{
-- if(!mAccountHandle.empty())
-- {
-- std::ostringstream stream;
--
-- LL_DEBUGS("Voice") << "requesting auto-accept rules" << LL_ENDL;
--
-- stream
-- << ""
-- << "" << mAccountHandle << ""
-- << ""
-- << "\n\n\n";
-+ std::ostringstream stream;
-+ stream
-+ << ""
-+ << "" << mAccountHandle << ""
-+ << "\n\n\n";
-
-- writeString(stream.str());
-- }
-+ writeString(stream.str());
- }
-
--void LLVoiceClient::sessionGroupCreateSendMessage()
-+void LLVoiceClient::sessionCreateSendMessage()
- {
-- if(!mAccountHandle.empty())
-- {
-- std::ostringstream stream;
--
-- LL_DEBUGS("Voice") << "creating session group" << LL_ENDL;
-+ LL_DEBUGS("Voice") << "requesting join: " << mNextSessionURI << LL_ENDL;
-
-- stream
-- << ""
-- << "" << mAccountHandle << ""
-- << "Normal"
-- << ""
-- << "\n\n\n";
--
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::sessionCreateSendMessage(sessionState *session, bool startAudio, bool startText)
--{
-- LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
--
-- session->mCreateInProgress = true;
-- if(startAudio)
-+ mSessionURI = mNextSessionURI;
-+ mNonSpatialChannel = !mNextSessionSpatial;
-+ mSessionResetOnClose = mNextSessionResetOnClose;
-+ mNextSessionResetOnClose = false;
-+ if(mNextSessionNoReconnect)
- {
-- session->mMediaConnectInProgress = true;
-+ // Clear the stashed URI so it can't reconnect
-+ mNextSessionURI.clear();
- }
-+ // Only p2p sessions are created with "no reconnect".
-+ mSessionP2P = mNextSessionNoReconnect;
-
- std::ostringstream stream;
- stream
-- << "mSIPURI << "\" action=\"Session.Create.1\">"
-+ << ""
- << "" << mAccountHandle << ""
-- << "" << session->mSIPURI << "";
-+ << "" << mSessionURI << "";
-
- static const std::string allowed_chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789"
- "-._~";
-
-- if(!session->mHash.empty())
-+ if(!mNextSessionHash.empty())
- {
- stream
-- << "" << LLURI::escape(session->mHash, allowed_chars) << ""
-+ << "" << LLURI::escape(mNextSessionHash, allowed_chars) << ""
- << "SHA1UserName";
- }
-
- stream
-- << "" << (startAudio?"true":"false") << ""
-- << "" << (startText?"true":"false") << ""
- << "" << mChannelName << ""
- << "\n\n\n";
- writeString(stream.str());
- }
-
--void LLVoiceClient::sessionGroupAddSessionSendMessage(sessionState *session, bool startAudio, bool startText)
-+void LLVoiceClient::sessionConnectSendMessage()
- {
-- LL_DEBUGS("Voice") << "requesting create: " << session->mSIPURI << LL_ENDL;
--
-- session->mCreateInProgress = true;
-- if(startAudio)
-- {
-- session->mMediaConnectInProgress = true;
-- }
--
-- std::string password;
-- if(!session->mHash.empty())
-- {
-- static const std::string allowed_chars =
-- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-- "0123456789"
-- "-._~"
-- ;
-- password = LLURI::escape(session->mHash, allowed_chars);
-- }
--
-- std::ostringstream stream;
-- stream
-- << "mSIPURI << "\" action=\"SessionGroup.AddSession.1\">"
-- << "" << session->mGroupHandle << ""
-- << "" << session->mSIPURI << ""
-- << "" << mChannelName << ""
-- << "" << (startAudio?"true":"false") << ""
-- << "" << (startText?"true":"false") << ""
-- << "" << password << ""
-- << "SHA1UserName"
-- << "\n\n\n"
-- ;
-+ LL_DEBUGS("Voice") << "connecting to session handle: " << mNextSessionHandle << LL_ENDL;
-
-- writeString(stream.str());
--}
--
--void LLVoiceClient::sessionMediaConnectSendMessage(sessionState *session)
--{
-- LL_DEBUGS("Voice") << "connecting audio to session handle: " << session->mHandle << LL_ENDL;
--
-- session->mMediaConnectInProgress = true;
-+ mSessionHandle = mNextSessionHandle;
-+ mSessionURI = mNextP2PSessionURI;
-+ mNextSessionHandle.clear(); // never want to re-use these.
-+ mNextP2PSessionURI.clear();
-+ mNonSpatialChannel = !mNextSessionSpatial;
-+ mSessionResetOnClose = mNextSessionResetOnClose;
-+ mNextSessionResetOnClose = false;
-+ // Joining by session ID is only used to answer p2p invitations, so we know this is a p2p session.
-+ mSessionP2P = true;
-
- std::ostringstream stream;
--
-- stream
-- << "mHandle << "\" action=\"Session.MediaConnect.1\">"
-- << "" << session->mGroupHandle << ""
-- << "" << session->mHandle << ""
-- << "Audio"
-- << "\n\n\n";
--
-- writeString(stream.str());
--}
--
--void LLVoiceClient::sessionTextConnectSendMessage(sessionState *session)
--{
-- LL_DEBUGS("Voice") << "connecting text to session handle: " << session->mHandle << LL_ENDL;
-
-- std::ostringstream stream;
--
- stream
-- << "mHandle << "\" action=\"Session.TextConnect.1\">"
-- << "" << session->mGroupHandle << ""
-- << "" << session->mHandle << ""
-+ << ""
-+ << "" << mSessionHandle << ""
-+ << "default"
- << "\n\n\n";
--
- writeString(stream.str());
- }
-
-@@ -2604,112 +2043,52 @@ void LLVoiceClient::sessionTerminate()
- mSessionTerminateRequested = true;
- }
-
--void LLVoiceClient::requestRelog()
-+void LLVoiceClient::sessionTerminateSendMessage()
- {
-- mSessionTerminateRequested = true;
-- mRelogRequested = true;
--}
-+ LL_DEBUGS("Voice") << "leaving session: " << mSessionURI << LL_ENDL;
-
--
--void LLVoiceClient::leaveAudioSession()
--{
-- if(mAudioSession)
-+ switch(getState())
- {
-- LL_DEBUGS("Voice") << "leaving session: " << mAudioSession->mSIPURI << LL_ENDL;
--
-- switch(getState())
-- {
-- case stateNoChannel:
-- // In this case, we want to pretend the join failed so our state machine doesn't get stuck.
-- // Skip the join failed transition state so we don't send out error notifications.
-- setState(stateJoinSessionFailedWaiting);
-- break;
-- case stateJoiningSession:
-- case stateSessionJoined:
-- case stateRunning:
-- if(!mAudioSession->mHandle.empty())
-- {
--
--#if RECORD_EVERYTHING
-- // HACK: for testing only
-- // Save looped recording
-- std::string savepath("/tmp/vivoxrecording");
-- {
-- time_t now = time(NULL);
-- const size_t BUF_SIZE = 64;
-- char time_str[BUF_SIZE]; /* Flawfinder: ignore */
--
-- strftime(time_str, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
-- savepath += time_str;
-- }
-- recordingLoopSave(savepath);
--#endif
--
-- sessionMediaDisconnectSendMessage(mAudioSession);
-- setState(stateLeavingSession);
-- }
-- else
-- {
-- LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
-- setState(stateSessionTerminated);
-- }
-- break;
-- case stateJoinSessionFailed:
-- case stateJoinSessionFailedWaiting:
-+ case stateNoChannel:
-+ // In this case, we want to pretend the join failed so our state machine doesn't get stuck.
-+ // Skip the join failed transition state so we don't send out error notifications.
-+ setState(stateJoinSessionFailedWaiting);
-+ break;
-+ case stateJoiningSession:
-+ case stateSessionJoined:
-+ case stateRunning:
-+ if(!mSessionHandle.empty())
-+ {
-+ sessionTerminateByHandle(mSessionHandle);
-+ setState(stateLeavingSession);
-+ }
-+ else
-+ {
-+ LL_WARNS("Voice") << "called with no session handle" << LL_ENDL;
- setState(stateSessionTerminated);
-- break;
--
-- default:
-- LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
-- break;
-- }
-- }
-- else
-- {
-- LL_WARNS("Voice") << "called with no active session" << LL_ENDL;
-- setState(stateSessionTerminated);
-+ }
-+ break;
-+ case stateJoinSessionFailed:
-+ case stateJoinSessionFailedWaiting:
-+ setState(stateSessionTerminated);
-+ break;
-+
-+ default:
-+ LL_WARNS("Voice") << "called from unknown state" << LL_ENDL;
-+ break;
- }
- }
-
--void LLVoiceClient::sessionTerminateSendMessage(sessionState *session)
-+void LLVoiceClient::sessionTerminateByHandle(std::string &sessionHandle)
- {
-- std::ostringstream stream;
--
-- LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << session->mHandle << LL_ENDL;
-- stream
-- << ""
-- << "" << session->mHandle << ""
-- << "\n\n\n";
--
-- writeString(stream.str());
--}
-+ LL_DEBUGS("Voice") << "Sending Session.Terminate with handle " << sessionHandle << LL_ENDL;
-
--void LLVoiceClient::sessionMediaDisconnectSendMessage(sessionState *session)
--{
- std::ostringstream stream;
--
-- LL_DEBUGS("Voice") << "Sending Session.MediaDisconnect with handle " << session->mHandle << LL_ENDL;
- stream
-- << ""
-- << "" << session->mGroupHandle << ""
-- << "" << session->mHandle << ""
-- << "Audio"
-- << "\n\n\n";
--
-- writeString(stream.str());
--
--}
--
--void LLVoiceClient::sessionTextDisconnectSendMessage(sessionState *session)
--{
-- std::ostringstream stream;
--
-- LL_DEBUGS("Voice") << "Sending Session.TextDisconnect with handle " << session->mHandle << LL_ENDL;
-- stream
-- << ""
-- << "" << session->mGroupHandle << ""
-- << "" << session->mHandle << ""
-- << "\n\n\n";
-+ << ""
-+ << "" << sessionHandle << ""
-+ << ""
-+ << "\n\n\n";
-
- writeString(stream.str());
- }
-@@ -2736,12 +2115,14 @@ void LLVoiceClient::getRenderDevicesSendMessage()
-
- void LLVoiceClient::clearCaptureDevices()
- {
-+ // MBW -- XXX -- do something here
- LL_DEBUGS("Voice") << "called" << LL_ENDL;
- mCaptureDevices.clear();
- }
-
- void LLVoiceClient::addCaptureDevice(const std::string& name)
- {
-+ // MBW -- XXX -- do something here
- LL_DEBUGS("Voice") << name << LL_ENDL;
-
- mCaptureDevices.push_back(name);
-@@ -2773,13 +2154,15 @@ void LLVoiceClient::setCaptureDevice(const std::string& name)
- }
-
- void LLVoiceClient::clearRenderDevices()
--{
-+{
-+ // MBW -- XXX -- do something here
- LL_DEBUGS("Voice") << "called" << LL_ENDL;
- mRenderDevices.clear();
- }
-
- void LLVoiceClient::addRenderDevice(const std::string& name)
- {
-+ // MBW -- XXX -- do something here
- LL_DEBUGS("Voice") << name << LL_ENDL;
- mRenderDevices.push_back(name);
- }
-@@ -2891,22 +2274,29 @@ void LLVoiceClient::tuningCaptureStopSendMessage()
-
- void LLVoiceClient::tuningSetMicVolume(float volume)
- {
-- int scaled_volume = scale_mic_volume(volume);
--
-- if(scaled_volume != mTuningMicVolume)
-+ int scaledVolume = ((int)(volume * 100.0f)) - 100;
-+ if(scaledVolume != mTuningMicVolume)
- {
-- mTuningMicVolume = scaled_volume;
-+ mTuningMicVolume = scaledVolume;
- mTuningMicVolumeDirty = true;
- }
- }
-
- void LLVoiceClient::tuningSetSpeakerVolume(float volume)
- {
-- int scaled_volume = scale_speaker_volume(volume);
-+ // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
-+ // Map it as follows: 0.0 -> -100, 0.5 -> 24, 1.0 -> 50
-+
-+ volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
-+ int scaledVolume = 24; // offset scaledVolume by its default level
-+ if(volume < 0.0f)
-+ scaledVolume += ((int)(volume * 248.0f)); // (24 - (-100)) * 2
-+ else
-+ scaledVolume += ((int)(volume * 52.0f)); // (50 - 24) * 2
-
-- if(scaled_volume != mTuningSpeakerVolume)
-+ if(scaledVolume != mTuningSpeakerVolume)
- {
-- mTuningSpeakerVolume = scaled_volume;
-+ mTuningSpeakerVolume = scaledVolume;
- mTuningSpeakerVolumeDirty = true;
- }
- }
-@@ -2945,193 +2335,67 @@ void LLVoiceClient::daemonDied()
- // The daemon died, so the connection is gone. Reset everything and start over.
- LL_WARNS("Voice") << "Connection to vivox daemon lost. Resetting state."<< LL_ENDL;
-
-+ closeSocket();
-+ removeAllParticipants();
-+
- // Try to relaunch the daemon
-- setState(stateDisableCleanup);
-+ setState(stateDisabled);
- }
-
- void LLVoiceClient::giveUp()
- {
- // All has failed. Clean up and stop trying.
- closeSocket();
-- deleteAllSessions();
-- deleteAllBuddies();
-+ removeAllParticipants();
-
- setState(stateJail);
- }
-
--static void oldSDKTransform (LLVector3 &left, LLVector3 &up, LLVector3 &at, LLVector3d &pos, LLVector3 &vel)
--{
-- F32 nat[3], nup[3], nl[3], nvel[3]; // the new at, up, left vectors and the new position and velocity
-- F64 npos[3];
--
-- // The original XML command was sent like this:
-- /*
-- << ""
-- << "" << pos[VX] << ""
-- << "" << pos[VZ] << ""
-- << "" << pos[VY] << ""
-- << ""
-- << ""
-- << "" << mAvatarVelocity[VX] << ""
-- << "" << mAvatarVelocity[VZ] << ""
-- << "" << mAvatarVelocity[VY] << ""
-- << ""
-- << ""
-- << "" << l.mV[VX] << ""
-- << "" << u.mV[VX] << ""
-- << "" << a.mV[VX] << ""
-- << ""
-- << ""
-- << "" << l.mV[VZ] << ""
-- << "" << u.mV[VY] << ""
-- << "" << a.mV[VZ] << ""
-- << ""
-- << ""
-- << "" << l.mV [VY] << ""
-- << "" << u.mV [VZ] << ""
-- << "" << a.mV [VY] << ""
-- << "";
-- */
--
--#if 1
-- // This was the original transform done when building the XML command
-- nat[0] = left.mV[VX];
-- nat[1] = up.mV[VX];
-- nat[2] = at.mV[VX];
--
-- nup[0] = left.mV[VZ];
-- nup[1] = up.mV[VY];
-- nup[2] = at.mV[VZ];
--
-- nl[0] = left.mV[VY];
-- nl[1] = up.mV[VZ];
-- nl[2] = at.mV[VY];
--
-- npos[0] = pos.mdV[VX];
-- npos[1] = pos.mdV[VZ];
-- npos[2] = pos.mdV[VY];
--
-- nvel[0] = vel.mV[VX];
-- nvel[1] = vel.mV[VZ];
-- nvel[2] = vel.mV[VY];
--
-- for(int i=0;i<3;++i) {
-- at.mV[i] = nat[i];
-- up.mV[i] = nup[i];
-- left.mV[i] = nl[i];
-- pos.mdV[i] = npos[i];
-- }
--
-- // This was the original transform done in the SDK
-- nat[0] = at.mV[2];
-- nat[1] = 0; // y component of at vector is always 0, this was up[2]
-- nat[2] = -1 * left.mV[2];
--
-- // We override whatever the application gives us
-- nup[0] = 0; // x component of up vector is always 0
-- nup[1] = 1; // y component of up vector is always 1
-- nup[2] = 0; // z component of up vector is always 0
--
-- nl[0] = at.mV[0];
-- nl[1] = 0; // y component of left vector is always zero, this was up[0]
-- nl[2] = -1 * left.mV[0];
--
-- npos[2] = pos.mdV[2] * -1.0;
-- npos[1] = pos.mdV[1];
-- npos[0] = pos.mdV[0];
--
-- for(int i=0;i<3;++i) {
-- at.mV[i] = nat[i];
-- up.mV[i] = nup[i];
-- left.mV[i] = nl[i];
-- pos.mdV[i] = npos[i];
-- }
--#else
-- // This is the compose of the two transforms (at least, that's what I'm trying for)
-- nat[0] = at.mV[VX];
-- nat[1] = 0; // y component of at vector is always 0, this was up[2]
-- nat[2] = -1 * up.mV[VZ];
--
-- // We override whatever the application gives us
-- nup[0] = 0; // x component of up vector is always 0
-- nup[1] = 1; // y component of up vector is always 1
-- nup[2] = 0; // z component of up vector is always 0
--
-- nl[0] = left.mV[VX];
-- nl[1] = 0; // y component of left vector is always zero, this was up[0]
-- nl[2] = -1 * left.mV[VY];
--
-- npos[0] = pos.mdV[VX];
-- npos[1] = pos.mdV[VZ];
-- npos[2] = pos.mdV[VY] * -1.0;
--
-- nvel[0] = vel.mV[VX];
-- nvel[1] = vel.mV[VZ];
-- nvel[2] = vel.mV[VY];
--
-- for(int i=0;i<3;++i) {
-- at.mV[i] = nat[i];
-- up.mV[i] = nup[i];
-- left.mV[i] = nl[i];
-- pos.mdV[i] = npos[i];
-- }
--
--#endif
--}
--
- void LLVoiceClient::sendPositionalUpdate(void)
- {
- std::ostringstream stream;
-
- if(mSpatialCoordsDirty)
- {
-- LLVector3 l, u, a, vel;
-- LLVector3d pos;
--
-- mSpatialCoordsDirty = false;
-+ LLVector3 l, u, a;
-
- // Always send both speaker and listener positions together.
- stream << ""
-- << "" << getAudioSessionHandle() << "";
-+ << "" << mSessionHandle << "";
-
- stream << "";
-
--// LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
- l = mAvatarRot.getLeftRow();
- u = mAvatarRot.getUpRow();
- a = mAvatarRot.getFwdRow();
-- pos = mAvatarPosition;
-- vel = mAvatarVelocity;
-+
-+ LL_DEBUGS("Voice") << "Sending speaker position " << mAvatarPosition << LL_ENDL;
-
-- // SLIM SDK: the old SDK was doing a transform on the passed coordinates that the new one doesn't do anymore.
-- // The old transform is replicated by this function.
-- oldSDKTransform(l, u, a, pos, vel);
--
- stream
- << ""
-- << "" << pos.mdV[VX] << ""
-- << "" << pos.mdV[VY] << ""
-- << "" << pos.mdV[VZ] << ""
-+ << "" << mAvatarPosition[VX] << ""
-+ << "" << mAvatarPosition[VZ] << ""
-+ << "" << mAvatarPosition[VY] << ""
- << ""
- << ""
-- << "" << vel.mV[VX] << ""
-- << "" << vel.mV[VY] << ""
-- << "" << vel.mV[VZ] << ""
-+ << "" << mAvatarVelocity[VX] << ""
-+ << "" << mAvatarVelocity[VZ] << ""
-+ << "" << mAvatarVelocity[VY] << ""
- << ""
- << ""
-- << "" << a.mV[VX] << ""
-- << "" << a.mV[VY] << ""
-- << "" << a.mV[VZ] << ""
-+ << "" << l.mV[VX] << ""
-+ << "" << u.mV[VX] << ""
-+ << "" << a.mV[VX] << ""
- << ""
- << ""
-- << "" << u.mV[VX] << ""
-+ << "" << l.mV[VZ] << ""
- << "" << u.mV[VY] << ""
-- << "" << u.mV[VZ] << ""
-+ << "" << a.mV[VZ] << ""
- << ""
- << ""
-- << "" << l.mV [VX] << ""
-- << "" << l.mV [VY] << ""
-- << "" << l.mV [VZ] << ""
-+ << "" << l.mV [VY] << ""
-+ << "" << u.mV [VZ] << ""
-+ << "" << a.mV [VY] << ""
- << "";
-
- stream << "";
-@@ -3167,158 +2431,43 @@ void LLVoiceClient::sendPositionalUpdate(void)
- l = earRot.getLeftRow();
- u = earRot.getUpRow();
- a = earRot.getFwdRow();
-- pos = earPosition;
-- vel = earVelocity;
-
--// LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
--
-- oldSDKTransform(l, u, a, pos, vel);
--
-+ LL_DEBUGS("Voice") << "Sending listener position " << earPosition << LL_ENDL;
-+
- stream
- << ""
-- << "" << pos.mdV[VX] << ""
-- << "" << pos.mdV[VY] << ""
-- << "" << pos.mdV[VZ] << ""
-+ << "" << earPosition[VX] << ""
-+ << "" << earPosition[VZ] << ""
-+ << "" << earPosition[VY] << ""
- << ""
- << ""
-- << "" << vel.mV[VX] << ""
-- << "" << vel.mV[VY] << ""
-- << "" << vel.mV[VZ] << ""
-+ << "" << earVelocity[VX] << ""
-+ << "" << earVelocity[VZ] << ""
-+ << "" << earVelocity[VY] << ""
- << ""
- << ""
-- << "" << a.mV[VX] << ""
-- << "" << a.mV[VY] << ""
-- << "" << a.mV[VZ] << ""
-+ << "" << l.mV[VX] << ""
-+ << "" << u.mV[VX] << ""
-+ << "" << a.mV[VX] << ""
- << ""
- << ""
-- << "" << u.mV[VX] << ""
-+ << "" << l.mV[VZ] << ""
- << "" << u.mV[VY] << ""
-- << "" << u.mV[VZ] << ""
-+ << "" << a.mV[VZ] << ""
- << ""
- << ""
-- << "" << l.mV [VX] << ""
-- << "" << l.mV [VY] << ""
-- << "" << l.mV [VZ] << ""
-+ << "" << l.mV [VY] << ""
-+ << "" << u.mV [VZ] << ""
-+ << "" << a.mV [VY] << ""
- << "";
-
--
- stream << "";
-
- stream << "\n\n\n";
- }
--
-- if(mAudioSession && mAudioSession->mVolumeDirty)
-- {
-- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
--
-- mAudioSession->mVolumeDirty = false;
--
-- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
-- {
-- participantState *p = iter->second;
--
-- if(p->mVolumeDirty)
-- {
-- // Can't set volume/mute for yourself
-- if(!p->mIsSelf)
-- {
-- int volume = p->mUserVolume;
-- bool mute = p->mOnMuteList;
--
-- // SLIM SDK: scale volume from 0-400 (with 100 as "normal") to 0-100 (with 56 as "normal")
-- if(volume < 100)
-- volume = (volume * 56) / 100;
-- else
-- volume = (((volume - 100) * (100 - 56)) / 300) + 56;
--
-- if(mute)
-- {
-- // SetParticipantMuteForMe doesn't work in p2p sessions.
-- // If we want the user to be muted, set their volume to 0 as well.
-- // This isn't perfect, but it will at least reduce their volume to a minimum.
-- volume = 0;
-- }
--
-- if(volume == 0)
-- mute = true;
--
-- LL_DEBUGS("Voice") << "Setting volume/mute for avatar " << p->mAvatarID << " to " << volume << (mute?"/true":"/false") << LL_ENDL;
--
-- // SLIM SDK: Send both volume and mute commands.
--
-- // Send a "volume for me" command for the user.
-- stream << ""
-- << "" << getAudioSessionHandle() << ""
-- << "" << p->mURI << ""
-- << "" << volume << ""
-- << "\n\n\n";
--
-- // Send a "mute for me" command for the user
-- stream << ""
-- << "" << getAudioSessionHandle() << ""
-- << "" << p->mURI << ""
-- << "" << (mute?"1":"0") << ""
-- << "\n\n\n";
-- }
--
-- p->mVolumeDirty = false;
-- }
-- }
-- }
--
-- buildLocalAudioUpdates(stream);
--
-- if(!stream.str().empty())
-- {
-- writeString(stream.str());
-- }
--
-- // Friends list updates can be huge, especially on the first voice login of an account with lots of friends.
-- // Batching them all together can choke SLVoice, so send them in separate writes.
-- sendFriendsListUpdates();
--}
--
--void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
--{
-- if(mCaptureDeviceDirty)
-- {
-- LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
--
-- stream
-- << ""
-- << "" << mCaptureDevice << ""
-- << ""
-- << "\n\n\n";
--
-- mCaptureDeviceDirty = false;
-- }
--}
--
--void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
--{
-- if(mRenderDeviceDirty)
-- {
-- LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
--
-- stream
-- << ""
-- << "" << mRenderDevice << ""
-- << ""
-- << "\n\n\n";
-- mRenderDeviceDirty = false;
-- }
--}
--
--void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
--{
-- buildSetCaptureDevice(stream);
--
-- buildSetRenderDevice(stream);
-
- if(mPTTDirty)
- {
-- mPTTDirty = false;
--
- // Send a local mute command.
- // NOTE that the state of "PTT" is the inverse of "local mute".
- // (i.e. when PTT is true, we send a mute command with "false", and vice versa)
-@@ -3329,337 +2478,119 @@ void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
- << "" << mConnectorHandle << ""
- << "" << (mPTT?"false":"true") << ""
- << "\n\n\n";
--
-+
- }
-+
-+ if(mVolumeDirty)
-+ {
-+ participantMap::iterator iter = mParticipantMap.begin();
-+
-+ for(; iter != mParticipantMap.end(); iter++)
-+ {
-+ participantState *p = iter->second;
-+
-+ if(p->mVolumeDirty)
-+ {
-+ int volume = p->mOnMuteList?0:p->mUserVolume;
-+
-+ LL_INFOS("Voice") << "Setting volume for avatar " << p->mAvatarID << " to " << volume << LL_ENDL;
-+
-+ // Send a mute/unumte command for the user (actually "volume for me").
-+ stream << ""
-+ << "" << mSessionHandle << ""
-+ << "" << p->mURI << ""
-+ << "" << volume << ""
-+ << "\n\n\n";
-
-+ p->mVolumeDirty = false;
-+ }
-+ }
-+ }
-+
- if(mSpeakerMuteDirty)
- {
-- const char *muteval = ((mSpeakerVolume == 0)?"true":"false");
--
-- mSpeakerMuteDirty = false;
--
-+ const char *muteval = ((mSpeakerVolume == -100)?"true":"false");
- LL_INFOS("Voice") << "Setting speaker mute to " << muteval << LL_ENDL;
-
- stream << ""
- << "" << mConnectorHandle << ""
- << "" << muteval << ""
-- << "\n\n\n";
--
-+ << "\n\n\n";
- }
-
- if(mSpeakerVolumeDirty)
- {
-- mSpeakerVolumeDirty = false;
--
- LL_INFOS("Voice") << "Setting speaker volume to " << mSpeakerVolume << LL_ENDL;
-
- stream << ""
- << "" << mConnectorHandle << ""
- << "" << mSpeakerVolume << ""
-- << "\n\n\n";
--
-+ << "\n\n\n";
- }
-
- if(mMicVolumeDirty)
- {
-- mMicVolumeDirty = false;
--
- LL_INFOS("Voice") << "Setting mic volume to " << mMicVolume << LL_ENDL;
-
- stream << ""
- << "" << mConnectorHandle << ""
- << "" << mMicVolume << ""
-- << "\n\n\n";
-+ << "\n\n\n";
- }
-
-
--}
--
--void LLVoiceClient::checkFriend(const LLUUID& id)
--{
-- std::string name;
-- buddyListEntry *buddy = findBuddy(id);
--
-- // Make sure we don't add a name before it's been looked up.
-- if(gCacheName->getFullName(id, name))
-+ // MBW -- XXX -- Maybe check to make sure the capture/render devices are in the current list here?
-+ if(mCaptureDeviceDirty)
- {
--
-- const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
-- bool canSeeMeOnline = false;
-- if(relationInfo && relationInfo->isRightGrantedTo(LLRelationship::GRANT_ONLINE_STATUS))
-- canSeeMeOnline = true;
--
-- // When we get here, mNeedsSend is true and mInSLFriends is false. Change them as necessary.
--
-- if(buddy)
-- {
-- // This buddy is already in both lists.
--
-- if(name != buddy->mDisplayName)
-- {
-- // The buddy is in the list with the wrong name. Update it with the correct name.
-- LL_WARNS("Voice") << "Buddy " << id << " has wrong name (\"" << buddy->mDisplayName << "\" should be \"" << name << "\"), updating."<< LL_ENDL;
-- buddy->mDisplayName = name;
-- buddy->mNeedsNameUpdate = true; // This will cause the buddy to be resent.
-- }
-- }
-- else
-- {
-- // This buddy was not in the vivox list, needs to be added.
-- buddy = addBuddy(sipURIFromID(id), name);
-- buddy->mUUID = id;
-- }
--
-- // In all the above cases, the buddy is in the SL friends list (which is how we got here).
-- buddy->mInSLFriends = true;
-- buddy->mCanSeeMeOnline = canSeeMeOnline;
-- buddy->mNameResolved = true;
--
-+ buildSetCaptureDevice(stream);
- }
-- else
-+
-+ if(mRenderDeviceDirty)
- {
-- // This name hasn't been looked up yet. Don't do anything with this buddy list entry until it has.
-- if(buddy)
-- {
-- buddy->mNameResolved = false;
-- }
--
-- // Initiate a lookup.
-- // The "lookup completed" callback will ensure that the friends list is rechecked after it completes.
-- lookupName(id);
-+ buildSetRenderDevice(stream);
- }
--}
--
--void LLVoiceClient::clearAllLists()
--{
-- // FOR TESTING ONLY
-
-- // This will send the necessary commands to delete ALL buddies, autoaccept rules, and block rules SLVoice tells us about.
-- buddyListMap::iterator buddy_it;
-- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
-+ mSpatialCoordsDirty = false;
-+ mPTTDirty = false;
-+ mVolumeDirty = false;
-+ mSpeakerVolumeDirty = false;
-+ mMicVolumeDirty = false;
-+ mSpeakerMuteDirty = false;
-+ mCaptureDeviceDirty = false;
-+ mRenderDeviceDirty = false;
-+
-+ if(!stream.str().empty())
- {
-- buddyListEntry *buddy = buddy_it->second;
-- buddy_it++;
--
-- std::ostringstream stream;
--
-- if(buddy->mInVivoxBuddies)
-- {
-- // delete this entry from the vivox buddy list
-- buddy->mInVivoxBuddies = false;
-- LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
-- }
--
-- if(buddy->mHasBlockListEntry)
-- {
-- // Delete the associated block list entry (so the block list doesn't fill up with junk)
-- buddy->mHasBlockListEntry = false;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
-- }
-- if(buddy->mHasAutoAcceptListEntry)
-- {
-- // Delete the associated auto-accept list entry (so the auto-accept list doesn't fill up with junk)
-- buddy->mHasAutoAcceptListEntry = false;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
-- }
--
- writeString(stream.str());
--
- }
- }
-
--void LLVoiceClient::sendFriendsListUpdates()
-+void LLVoiceClient::buildSetCaptureDevice(std::ostringstream &stream)
- {
-- if(mBuddyListMapPopulated && mBlockRulesListReceived && mAutoAcceptRulesListReceived && mFriendsListDirty)
-- {
-- mFriendsListDirty = false;
--
-- if(0)
-- {
-- // FOR TESTING ONLY -- clear all buddy list, block list, and auto-accept list entries.
-- clearAllLists();
-- return;
-- }
--
-- LL_INFOS("Voice") << "Checking vivox buddy list against friends list..." << LL_ENDL;
--
-- buddyListMap::iterator buddy_it;
-- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
-- {
-- // reset the temp flags in the local buddy list
-- buddy_it->second->mInSLFriends = false;
-- }
--
-- // correlate with the friends list
-- {
-- LLCollectAllBuddies collect;
-- LLAvatarTracker::instance().applyFunctor(collect);
-- LLCollectAllBuddies::buddy_map_t::const_iterator it = collect.mOnline.begin();
-- LLCollectAllBuddies::buddy_map_t::const_iterator end = collect.mOnline.end();
--
-- for ( ; it != end; ++it)
-- {
-- checkFriend(it->second);
-- }
-- it = collect.mOffline.begin();
-- end = collect.mOffline.end();
-- for ( ; it != end; ++it)
-- {
-- checkFriend(it->second);
-- }
-- }
--
-- LL_INFOS("Voice") << "Sending friend list updates..." << LL_ENDL;
--
-- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end();)
-- {
-- buddyListEntry *buddy = buddy_it->second;
-- buddy_it++;
--
-- // Ignore entries that aren't resolved yet.
-- if(buddy->mNameResolved)
-- {
-- std::ostringstream stream;
--
-- if(buddy->mInSLFriends && (!buddy->mInVivoxBuddies || buddy->mNeedsNameUpdate))
-- {
-- if(mNumberOfAliases > 0)
-- {
-- // Add (or update) this entry in the vivox buddy list
-- buddy->mInVivoxBuddies = true;
-- buddy->mNeedsNameUpdate = false;
-- LL_DEBUGS("Voice") << "add/update " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
-- stream
-- << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "" << buddy->mDisplayName << ""
-- << "" // Without this, SLVoice doesn't seem to parse the command.
-- << "0"
-- << "\n\n\n";
-- }
-- }
-- else if(!buddy->mInSLFriends)
-- {
-- // This entry no longer exists in your SL friends list. Remove all traces of it from the Vivox buddy list.
-- if(buddy->mInVivoxBuddies)
-- {
-- // delete this entry from the vivox buddy list
-- buddy->mInVivoxBuddies = false;
-- LL_DEBUGS("Voice") << "delete " << buddy->mURI << " (" << buddy->mDisplayName << ")" << LL_ENDL;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
-- }
--
-- if(buddy->mHasBlockListEntry)
-- {
-- // Delete the associated block list entry, if any
-- buddy->mHasBlockListEntry = false;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
-- }
-- if(buddy->mHasAutoAcceptListEntry)
-- {
-- // Delete the associated auto-accept list entry, if any
-- buddy->mHasAutoAcceptListEntry = false;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
-- }
-- }
--
-- if(buddy->mInSLFriends)
-- {
--
-- if(buddy->mCanSeeMeOnline)
-- {
-- // Buddy should not be blocked.
--
-- // If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
--
-- // If the buddy has a block list entry, delete it.
-- if(buddy->mHasBlockListEntry)
-- {
-- buddy->mHasBlockListEntry = false;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
--
--
-- // If we just deleted a block list entry, add an auto-accept entry.
-- if(!buddy->mHasAutoAcceptListEntry)
-- {
-- buddy->mHasAutoAcceptListEntry = true;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "0"
-- << "\n\n\n";
-- }
-- }
-- }
-- else
-- {
-- // Buddy should be blocked.
--
-- // If this buddy doesn't already have either a block or autoaccept list entry, we'll update their status when we receive a SubscriptionEvent.
--
-- // If this buddy has an autoaccept entry, delete it
-- if(buddy->mHasAutoAcceptListEntry)
-- {
-- buddy->mHasAutoAcceptListEntry = false;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "\n\n\n";
--
-- // If we just deleted an auto-accept entry, add a block list entry.
-- if(!buddy->mHasBlockListEntry)
-- {
-- buddy->mHasBlockListEntry = true;
-- stream << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "1"
-- << "\n\n\n";
-- }
-- }
-- }
-+ LL_DEBUGS("Voice") << "Setting input device = \"" << mCaptureDevice << "\"" << LL_ENDL;
-+
-+ stream
-+ << ""
-+ << "" << mCaptureDevice << ""
-+ << ""
-+ << "\n\n\n";
-+}
-
-- if(!buddy->mInSLFriends && !buddy->mInVivoxBuddies)
-- {
-- // Delete this entry from the local buddy list. This should NOT invalidate the iterator,
-- // since it has already been incremented to the next entry.
-- deleteBuddy(buddy->mURI);
-- }
-+void LLVoiceClient::buildSetRenderDevice(std::ostringstream &stream)
-+{
-+ LL_DEBUGS("Voice") << "Setting output device = \"" << mRenderDevice << "\"" << LL_ENDL;
-
-- }
-- writeString(stream.str());
-- }
-- }
-- }
-+ stream
-+ << ""
-+ << "" << mRenderDevice << ""
-+ << ""
-+ << "\n\n\n";
- }
-
- /////////////////////////////
- // Response/Event handlers
-
--void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID)
-+void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle)
- {
- if(statusCode != 0)
- {
-@@ -3669,7 +2600,6 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
- else
- {
- // Connector created, move forward.
-- LL_INFOS("Voice") << "Connector.Create succeeded, Vivox SDK version is " << versionID << LL_ENDL;
- mConnectorHandle = connectorHandle;
- if(getState() == stateConnectorStarting)
- {
-@@ -3678,7 +2608,7 @@ void LLVoiceClient::connectorCreateResponse(int statusCode, std::string &statusS
- }
- }
-
--void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases)
-+void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std::string &accountHandle)
- {
- LL_DEBUGS("Voice") << "Account.Login response (" << statusCode << "): " << statusString << LL_ENDL;
-
-@@ -3699,8 +2629,7 @@ void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std
- {
- // Login succeeded, move forward.
- mAccountHandle = accountHandle;
-- mNumberOfAliases = numberOfAliases;
-- // This needs to wait until the AccountLoginStateChangeEvent is received.
-+ // MBW -- XXX -- This needs to wait until the LoginStateChangeEvent is received.
- // if(getState() == stateLoggingIn)
- // {
- // setState(stateLoggedIn);
-@@ -3708,91 +2637,106 @@ void LLVoiceClient::loginResponse(int statusCode, std::string &statusString, std
- }
- }
-
--void LLVoiceClient::sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
--{
-- sessionState *session = findSessionBeingCreatedByURI(requestId);
--
-- if(session)
-- {
-- session->mCreateInProgress = false;
-- }
--
-+void LLVoiceClient::channelGetListResponse(int statusCode, std::string &statusString)
-+{
- if(statusCode != 0)
- {
-- LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
-- if(session)
-- {
-- session->mErrorStatusCode = statusCode;
-- session->mErrorStatusString = statusString;
-- if(session == mAudioSession)
-- {
-- setState(stateJoinSessionFailed);
-- }
-- else
-- {
-- reapSession(session);
-- }
-- }
-+ LL_WARNS("Voice") << "Account.ChannelGetList response failure: " << statusString << LL_ENDL;
-+ switchChannel();
- }
- else
- {
-- LL_INFOS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
-- if(session)
-+ // Got the channel list, try to do a lookup.
-+ std::string uri = findChannelURI(mChannelName);
-+ if(uri.empty())
-+ {
-+ // Lookup failed, can't join a channel for this area.
-+ LL_INFOS("Voice") << "failed to map channel name: " << mChannelName << LL_ENDL;
-+ }
-+ else
- {
-- setSessionHandle(session, sessionHandle);
-+ // We have a sip URL for this area.
-+ LL_INFOS("Voice") << "mapped channel " << mChannelName << " to URI "<< uri << LL_ENDL;
- }
-+
-+ // switchChannel with an empty uri string will do the right thing (leave channel and not rejoin)
-+ switchChannel(uri);
- }
- }
-
--void LLVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle)
-+void LLVoiceClient::sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle)
- {
-- sessionState *session = findSessionBeingCreatedByURI(requestId);
--
-- if(session)
-- {
-- session->mCreateInProgress = false;
-- }
--
- if(statusCode != 0)
- {
-- LL_WARNS("Voice") << "SessionGroup.AddSession response failure (" << statusCode << "): " << statusString << LL_ENDL;
-- if(session)
-+ LL_WARNS("Voice") << "Session.Create response failure (" << statusCode << "): " << statusString << LL_ENDL;
-+// if(statusCode == 1015)
-+// {
-+// if(getState() == stateJoiningSession)
-+// {
-+// // this happened during a real join. Going to sessionTerminated should cause a retry in appropriate cases.
-+// LL_WARNS("Voice") << "session handle \"" << sessionHandle << "\", mSessionStateEventHandle \"" << mSessionStateEventHandle << "\""<< LL_ENDL;
-+// if(!sessionHandle.empty())
-+// {
-+// // This session is bad. Terminate it.
-+// mSessionHandle = sessionHandle;
-+// sessionTerminateByHandle(sessionHandle);
-+// setState(stateLeavingSession);
-+// }
-+// else if(!mSessionStateEventHandle.empty())
-+// {
-+// mSessionHandle = mSessionStateEventHandle;
-+// sessionTerminateByHandle(mSessionStateEventHandle);
-+// setState(stateLeavingSession);
-+// }
-+// else
-+// {
-+// setState(stateSessionTerminated);
-+// }
-+// }
-+// else
-+// {
-+// // We didn't think we were in the middle of a join. Don't change state.
-+// LL_WARNS("Voice") << "Not in stateJoiningSession, ignoring" << LL_ENDL;
-+// }
-+// }
-+// else
- {
-- session->mErrorStatusCode = statusCode;
-- session->mErrorStatusString = statusString;
-- if(session == mAudioSession)
-- {
-- setState(stateJoinSessionFailed);
-- }
-- else
-- {
-- reapSession(session);
-- }
-+ mVivoxErrorStatusCode = statusCode;
-+ mVivoxErrorStatusString = statusString;
-+ setState(stateJoinSessionFailed);
- }
- }
- else
- {
-- LL_DEBUGS("Voice") << "SessionGroup.AddSession response received (success), session handle is " << sessionHandle << LL_ENDL;
-- if(session)
-+ LL_DEBUGS("Voice") << "Session.Create response received (success), session handle is " << sessionHandle << LL_ENDL;
-+ if(getState() == stateJoiningSession)
- {
-- setSessionHandle(session, sessionHandle);
-+ // This is also grabbed in the SessionStateChangeEvent handler, but it might be useful to have it early...
-+ mSessionHandle = sessionHandle;
-+ }
-+ else
-+ {
-+ // We should never get a session.create response in any state except stateJoiningSession. Things are out of sync. Kill this session.
-+ sessionTerminateByHandle(sessionHandle);
- }
- }
- }
-
--void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString)
-+void LLVoiceClient::sessionConnectResponse(int statusCode, std::string &statusString)
- {
-- sessionState *session = findSession(requestId);
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Session.Connect response failure (" << statusCode << "): " << statusString << LL_ENDL;
-- if(session)
-+// if(statusCode == 1015)
-+// {
-+// LL_WARNS("Voice") << "terminating existing session" << LL_ENDL;
-+// sessionTerminate();
-+// }
-+// else
- {
-- session->mMediaConnectInProgress = false;
-- session->mErrorStatusCode = statusCode;
-- session->mErrorStatusString = statusString;
-- if(session == mAudioSession)
-- setState(stateJoinSessionFailed);
-+ mVivoxErrorStatusCode = statusCode;
-+ mVivoxErrorStatusString = statusString;
-+ setState(stateJoinSessionFailed);
- }
- }
- else
-@@ -3801,12 +2745,27 @@ void LLVoiceClient::sessionConnectResponse(std::string &requestId, int statusCod
- }
- }
-
-+void LLVoiceClient::sessionTerminateResponse(int statusCode, std::string &statusString)
-+{
-+ if(statusCode != 0)
-+ {
-+ LL_WARNS("Voice") << "Session.Terminate response failure: (" << statusCode << "): " << statusString << LL_ENDL;
-+ if(getState() == stateLeavingSession)
-+ {
-+ // This is probably "(404): Server reporting Failure. Not a member of this conference."
-+ // Do this so we don't get stuck.
-+ setState(stateSessionTerminated);
-+ }
-+ }
-+
-+}
-+
- void LLVoiceClient::logoutResponse(int statusCode, std::string &statusString)
- {
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL;
-- // Should this ever fail? do we care if it does?
-+ // MBW -- XXX -- Should this ever fail? do we care if it does?
- }
-
- if(getState() == stateLoggingOut)
-@@ -3820,7 +2779,7 @@ void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statu
- if(statusCode != 0)
- {
- LL_WARNS("Voice") << "Connector.InitiateShutdown response failure: " << statusString << LL_ENDL;
-- // Should this ever fail? do we care if it does?
-+ // MBW -- XXX -- Should this ever fail? do we care if it does?
- }
-
- mConnected = false;
-@@ -3831,277 +2790,109 @@ void LLVoiceClient::connectorShutdownResponse(int statusCode, std::string &statu
- }
- }
-
--void LLVoiceClient::sessionAddedEvent(
-+void LLVoiceClient::sessionStateChangeEvent(
- std::string &uriString,
-- std::string &alias,
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle,
-+ int statusCode,
-+ std::string &statusString,
-+ std::string &sessionHandle,
-+ int state,
- bool isChannel,
-- bool incoming,
-- std::string &nameString,
-- std::string &applicationString)
-+ std::string &nameString)
- {
-- sessionState *session = NULL;
--
-- LL_INFOS("Voice") << "session " << uriString << ", alias " << alias << ", name " << nameString << " handle " << sessionHandle << LL_ENDL;
--
-- session = addSession(uriString, sessionHandle);
-- if(session)
-+ switch(state)
- {
-- session->mGroupHandle = sessionGroupHandle;
-- session->mIsChannel = isChannel;
-- session->mIncoming = incoming;
-- session->mAlias = alias;
--
-- // Generate a caller UUID -- don't need to do this for channels
-- if(!session->mIsChannel)
-- {
-- if(IDFromName(session->mSIPURI, session->mCallerID))
-+ case 4: // I see this when joining the session
-+ LL_INFOS("Voice") << "joined session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << LL_ENDL;
-+
-+ // Session create succeeded, move forward.
-+ mSessionStateEventHandle = sessionHandle;
-+ mSessionStateEventURI = uriString;
-+ if(sessionHandle == mSessionHandle)
- {
-- // Normal URI(base64-encoded UUID)
-+ // This is the session we're joining.
-+ if(getState() == stateJoiningSession)
-+ {
-+ setState(stateSessionJoined);
-+ //RN: the uriString being returned by vivox here is actually your account uri, not the channel
-+ // you are attempting to join, so ignore it
-+ //LL_DEBUGS("Voice") << "received URI " << uriString << "(previously " << mSessionURI << ")" << LL_ENDL;
-+ //mSessionURI = uriString;
-+ }
- }
-- else if(!session->mAlias.empty() && IDFromName(session->mAlias, session->mCallerID))
-+ else if(sessionHandle == mNextSessionHandle)
- {
-- // Wrong URI, but an alias is available. Stash the incoming URI as an alternate
-- session->mAlternateSIPURI = session->mSIPURI;
--
-- // and generate a proper URI from the ID.
-- setSessionURI(session, sipURIFromID(session->mCallerID));
-+// LL_DEBUGS("Voice") << "received URI " << uriString << ", name " << nameString << " for next session (handle " << mNextSessionHandle << ")" << LL_ENDL;
- }
- 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->mSynthesizedCallerID = true;
--
-- // Can't look up the name in this case -- we have to extract it from the URI.
-- std::string namePortion = nameFromsipURI(session->mSIPURI);
-- if(namePortion.empty())
-- {
-- // Didn't seem to be a SIP URI, just use the whole provided name.
-- namePortion = nameString;
-- }
--
-- // Some incoming names may be separated with an underscore instead of a space. Fix this.
-- LLStringUtil::replaceChar(namePortion, '_', ' ');
--
-- // Act like we just finished resolving the name (this stores it in all the right places)
-- avatarNameResolved(session->mCallerID, namePortion);
-+ LL_WARNS("Voice") << "joining unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << LL_ENDL;
-+ // MBW -- XXX -- Should we send a Session.Terminate here?
- }
--
-- LL_INFOS("Voice") << "caller ID: " << session->mCallerID << LL_ENDL;
--
-- if(!session->mSynthesizedCallerID)
-- {
-- // If we got here, we don't have a proper name. Initiate a lookup.
-- lookupName(session->mCallerID);
-- }
-- }
-- }
--}
--
--void LLVoiceClient::sessionGroupAddedEvent(std::string &sessionGroupHandle)
--{
-- LL_DEBUGS("Voice") << "handle " << sessionGroupHandle << LL_ENDL;
--
--#if USE_SESSION_GROUPS
-- if(mMainSessionGroupHandle.empty())
-- {
-- // This is the first (i.e. "main") session group. Save its handle.
-- mMainSessionGroupHandle = sessionGroupHandle;
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Already had a session group handle " << mMainSessionGroupHandle << LL_ENDL;
-- }
--#endif
--}
--
--void LLVoiceClient::joinedAudioSession(sessionState *session)
--{
-- if(mAudioSession != session)
-- {
-- sessionState *oldSession = mAudioSession;
--
-- mAudioSession = session;
-- mAudioSessionChanged = true;
--
-- // The old session may now need to be deleted.
-- reapSession(oldSession);
-- }
--
-- // This is the session we're joining.
-- if(getState() == stateJoiningSession)
-- {
-- setState(stateSessionJoined);
--
-- // SLIM SDK: we don't always receive a participant state change for ourselves when joining a channel now.
-- // Add the current user as a participant here.
-- participantState *participant = session->addParticipant(sipURIFromName(mAccountName));
-- if(participant)
-- {
-- participant->mIsSelf = true;
-- lookupName(participant->mAvatarID);
-+
-+ break;
-+ case 5: // I see this when leaving the session
-+ LL_INFOS("Voice") << "left session " << uriString << ", name " << nameString << " handle " << mNextSessionHandle << LL_ENDL;
-
-- LL_INFOS("Voice") << "added self as participant \"" << participant->mAccountName
-- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-- }
--
-- if(!session->mIsChannel)
-- {
-- // this is a p2p session. Make sure the other end is added as a participant.
-- participantState *participant = session->addParticipant(session->mSIPURI);
-- if(participant)
-+ // Set the session handle to the empty string. If we get back to stateJoiningSession, we'll want to wait for the new session handle.
-+ if(sessionHandle == mSessionHandle)
- {
-- if(participant->mAvatarIDValid)
-+ // MBW -- XXX -- I think this is no longer necessary, now that we've got mNextSessionURI/mNextSessionHandle
-+ // mSessionURI.clear();
-+ // clear the session handle here just for sanity.
-+ mSessionHandle.clear();
-+ if(mSessionResetOnClose)
- {
-- lookupName(participant->mAvatarID);
-- }
-- else if(!session->mName.empty())
-- {
-- participant->mDisplayName = session->mName;
-- avatarNameResolved(participant->mAvatarID, session->mName);
-+ mSessionResetOnClose = false;
-+ mNonSpatialChannel = false;
-+ mNextSessionSpatial = true;
-+ parcelChanged();
- }
--
-- // TODO: Question: Do we need to set up mAvatarID/mAvatarIDValid here?
-- LL_INFOS("Voice") << "added caller as participant \"" << participant->mAccountName
-- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-- }
-- }
-- }
--}
--
--void LLVoiceClient::sessionRemovedEvent(
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle)
--{
-- LL_INFOS("Voice") << "handle " << sessionHandle << LL_ENDL;
--
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- leftAudioSession(session);
--
-- // This message invalidates the session's handle. Set it to empty.
-- setSessionHandle(session);
--
-- // Reset the media state (we now have no info)
-- session->mMediaStreamState = streamStateUnknown;
-- session->mTextStreamState = streamStateUnknown;
--
-- // Conditionally delete the session
-- reapSession(session);
-- }
-- else
-- {
-- LL_WARNS("Voice") << "unknown session " << sessionHandle << " removed" << LL_ENDL;
-- }
--}
--
--void LLVoiceClient::reapSession(sessionState *session)
--{
-- if(session)
-- {
-- if(!session->mHandle.empty())
-- {
-- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (non-null session handle)" << LL_ENDL;
-- }
-- else if(session->mCreateInProgress)
-- {
-- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (create in progress)" << LL_ENDL;
-- }
-- else if(session->mMediaConnectInProgress)
-- {
-- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (connect in progress)" << LL_ENDL;
-- }
-- else if(session == mAudioSession)
-- {
-- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the current session)" << LL_ENDL;
-- }
-- else if(session == mNextAudioSession)
-- {
-- LL_DEBUGS("Voice") << "NOT deleting session " << session->mSIPURI << " (it's the next session)" << LL_ENDL;
-- }
-- else
-- {
-- // TODO: Question: Should we check for queued text messages here?
-- // We don't have a reason to keep tracking this session, so just delete it.
-- LL_DEBUGS("Voice") << "deleting session " << session->mSIPURI << LL_ENDL;
-- deleteSession(session);
-- session = NULL;
-- }
-- }
-- else
-- {
--// LL_DEBUGS("Voice") << "session is NULL" << LL_ENDL;
-- }
--}
--
--// Returns true if the session seems to indicate we've moved to a region on a different voice server
--bool LLVoiceClient::sessionNeedsRelog(sessionState *session)
--{
-- bool result = false;
--
-- if(session != NULL)
-- {
-- // Only make this check for spatial channels (so it won't happen for group or p2p calls)
-- if(session->mIsSpatial)
-- {
-- std::string::size_type atsign;
-
-- atsign = session->mSIPURI.find("@");
--
-- if(atsign != std::string::npos)
-- {
-- std::string urihost = session->mSIPURI.substr(atsign + 1);
-- if(stricmp(urihost.c_str(), mVoiceSIPURIHostName.c_str()))
-+ removeAllParticipants();
-+
-+ switch(getState())
- {
-- // The hostname in this URI is different from what we expect. This probably means we need to relog.
-+ case stateJoiningSession:
-+ case stateSessionJoined:
-+ case stateRunning:
-+ case stateLeavingSession:
-+ case stateJoinSessionFailed:
-+ case stateJoinSessionFailedWaiting:
-+ // normal transition
-+ LL_INFOS("Voice") << "left session " << sessionHandle << "in state " << state2string(getState()) << LL_ENDL;
-+ setState(stateSessionTerminated);
-+ break;
-
-- // We could make a ProvisionVoiceAccountRequest and compare the result with the current values of
-- // mVoiceSIPURIHostName and mVoiceAccountServerURI to be really sure, but this is a pretty good indicator.
-+ case stateSessionTerminated:
-+ // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
-+ LL_WARNS("Voice") << "left session " << sessionHandle << "in state " << state2string(getState()) << LL_ENDL;
-+ break;
-
-- result = true;
-+ default:
-+ LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
-+ setState(stateSessionTerminated);
-+ break;
- }
-+
-+ // store status values for later notification of observers
-+ mVivoxErrorStatusCode = statusCode;
-+ mVivoxErrorStatusString = statusString;
-+ }
-+ else
-+ {
-+ LL_INFOS("Voice") << "leaving unknown session handle " << sessionHandle << ", URI " << uriString << ", name " << nameString << LL_ENDL;
- }
-- }
-- }
--
-- return result;
--}
-
--void LLVoiceClient::leftAudioSession(
-- sessionState *session)
--{
-- if(mAudioSession == session)
-- {
-- switch(getState())
-- {
-- case stateJoiningSession:
-- case stateSessionJoined:
-- case stateRunning:
-- case stateLeavingSession:
-- case stateJoinSessionFailed:
-- case stateJoinSessionFailedWaiting:
-- // normal transition
-- LL_DEBUGS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
-- setState(stateSessionTerminated);
-- break;
--
-- case stateSessionTerminated:
-- // this will happen sometimes -- there are cases where we send the terminate and then go straight to this state.
-- LL_WARNS("Voice") << "left session " << session->mHandle << " in state " << state2string(getState()) << LL_ENDL;
-- break;
--
-- default:
-- LL_WARNS("Voice") << "unexpected SessionStateChangeEvent (left session) in state " << state2string(getState()) << LL_ENDL;
-- setState(stateSessionTerminated);
-- break;
-- }
-+ mSessionStateEventHandle.clear();
-+ mSessionStateEventURI.clear();
-+ break;
-+ default:
-+ LL_WARNS("Voice") << "unknown state: " << state << LL_ENDL;
-+ break;
- }
- }
-
--void LLVoiceClient::accountLoginStateChangeEvent(
-+void LLVoiceClient::loginStateChangeEvent(
- std::string &accountHandle,
- int statusCode,
- std::string &statusString,
-@@ -4134,571 +2925,110 @@ void LLVoiceClient::accountLoginStateChangeEvent(
- }
- }
-
--void LLVoiceClient::mediaStreamUpdatedEvent(
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle,
-- int statusCode,
-- std::string &statusString,
-- int state,
-- bool incoming)
-+void LLVoiceClient::sessionNewEvent(
-+ std::string &accountHandle,
-+ std::string &eventSessionHandle,
-+ int state,
-+ std::string &nameString,
-+ std::string &uriString)
- {
-- sessionState *session = findSession(sessionHandle);
--
-- LL_DEBUGS("Voice") << "session " << sessionHandle << ", status code " << statusCode << ", string \"" << statusString << "\"" << LL_ENDL;
-+ LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
-
-- if(session)
-- {
-- // We know about this session
--
-- // Save the state for later use
-- session->mMediaStreamState = state;
--
-- switch(statusCode)
-- {
-- case 0:
-- case 200:
-- // generic success
-- // Don't change the saved error code (it may have been set elsewhere)
-- break;
-- default:
-- // save the status code for later
-- session->mErrorStatusCode = statusCode;
-- break;
-- }
--
-- switch(state)
-- {
-- case streamStateIdle:
-- // Standard "left audio session"
-- session->mVoiceEnabled = false;
-- session->mMediaConnectInProgress = false;
-- leftAudioSession(session);
-- break;
--
-- case streamStateConnected:
-- session->mVoiceEnabled = true;
-- session->mMediaConnectInProgress = false;
-- joinedAudioSession(session);
-- break;
--
-- case streamStateRinging:
-- if(incoming)
-- {
-- // Send the voice chat invite to the GUI layer
-- // TODO: Question: Should we correlate with the mute list here?
-- session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
-- session->mVoiceInvitePending = true;
-- if(session->mName.empty())
-- {
-- lookupName(session->mCallerID);
-- }
-- else
-- {
-- // Act like we just finished resolving the name
-- avatarNameResolved(session->mCallerID, session->mName);
-- }
-- }
-- break;
--
-- default:
-- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
-- break;
--
-- }
--
-- }
-- else
-+ switch(state)
- {
-- LL_WARNS("Voice") << "session " << sessionHandle << "not found"<< LL_ENDL;
-- }
--}
-+ case 0:
-+ {
-+ LL_DEBUGS("Voice") << "session handle = " << eventSessionHandle << ", name = " << nameString << ", uri = " << uriString << LL_ENDL;
-
--void LLVoiceClient::textStreamUpdatedEvent(
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle,
-- bool enabled,
-- int state,
-- bool incoming)
--{
-- sessionState *session = findSession(sessionHandle);
--
-- if(session)
-- {
-- // Save the state for later use
-- session->mTextStreamState = state;
--
-- // We know about this session
-- switch(state)
-- {
-- case 0: // We see this when the text stream closes
-- LL_DEBUGS("Voice") << "stream closed" << LL_ENDL;
-- break;
--
-- case 1: // We see this on an incoming call from the Connector
-- // Try to send any text messages queued for this session.
-- sendQueuedTextMessages(session);
--
-- // Send the text chat invite to the GUI layer
-- // TODO: Question: Should we correlate with the mute list here?
-- session->mTextInvitePending = true;
-- if(session->mName.empty())
-+ LLUUID caller_id;
-+ if(IDFromName(nameString, caller_id))
- {
-- lookupName(session->mCallerID);
-+ gIMMgr->inviteToSession(
-+ LLIMMgr::computeSessionID(
-+ IM_SESSION_P2P_INVITE,
-+ caller_id),
-+ LLStringUtil::null,
-+ caller_id,
-+ LLStringUtil::null,
-+ IM_SESSION_P2P_INVITE,
-+ LLIMMgr::INVITATION_TYPE_VOICE,
-+ eventSessionHandle);
- }
- else
- {
-- // Act like we just finished resolving the name
-- avatarNameResolved(session->mCallerID, session->mName);
-+ LL_WARNS("Voice") << "Could not generate caller id from uri " << uriString << LL_ENDL;
- }
-- break;
--
-- default:
-- LL_WARNS("Voice") << "unknown state " << state << LL_ENDL;
-- break;
--
-- }
-+ }
-+ break;
-+
-+ default:
-+ LL_WARNS("Voice") << "unknown state: " << state << LL_ENDL;
-+ break;
- }
- }
-
--void LLVoiceClient::participantAddedEvent(
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle,
-+void LLVoiceClient::participantStateChangeEvent(
- std::string &uriString,
-- std::string &alias,
-+ int statusCode,
-+ std::string &statusString,
-+ int state,
- std::string &nameString,
- std::string &displayNameString,
- int participantType)
- {
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- participantState *participant = session->addParticipant(uriString);
-- if(participant)
-- {
-- participant->mAccountName = nameString;
--
-- LL_DEBUGS("Voice") << "added participant \"" << participant->mAccountName
-- << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
-+ participantState *participant = NULL;
-+ LL_DEBUGS("Voice") << "state is " << state << LL_ENDL;
-
-- if(participant->mAvatarIDValid)
-+ switch(state)
-+ {
-+ case 7: // I see this when a participant joins
-+ participant = addParticipant(uriString);
-+ if(participant)
- {
-- // Initiate a lookup
-- lookupName(participant->mAvatarID);
-+ participant->mName = nameString;
-+ LL_DEBUGS("Voice") << "added participant \"" << participant->mName
-+ << "\" (" << participant->mAvatarID << ")"<< LL_ENDL;
- }
-- else
-+ break;
-+ case 9: // I see this when a participant leaves
-+ participant = findParticipant(uriString);
-+ if(participant)
- {
-- // If we don't have a valid avatar UUID, we need to fill in the display name to make the active speakers floater work.
-- std::string namePortion = nameFromsipURI(uriString);
-- if(namePortion.empty())
-- {
-- // Problem with the SIP URI, fall back to the display name
-- namePortion = displayNameString;
-- }
-- if(namePortion.empty())
-- {
-- // Problems with both of the above, fall back to the account name
-- namePortion = nameString;
-- }
--
-- // Set the display name (which is a hint to the active speakers window not to do its own lookup)
-- participant->mDisplayName = namePortion;
-- avatarNameResolved(participant->mAvatarID, namePortion);
-+ removeParticipant(participant);
- }
-- }
-- }
--}
--
--void LLVoiceClient::participantRemovedEvent(
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle,
-- std::string &uriString,
-- std::string &alias,
-- std::string &nameString)
--{
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- participantState *participant = session->findParticipant(uriString);
-- if(participant)
-- {
-- session->removeParticipant(participant);
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "unknown participant " << uriString << LL_ENDL;
-- }
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
-+ break;
-+ default:
-+ LL_DEBUGS("Voice") << "unknown state: " << state << LL_ENDL;
-+ break;
- }
- }
-
--
--void LLVoiceClient::participantUpdatedEvent(
-- std::string &sessionHandle,
-- std::string &sessionGroupHandle,
-+void LLVoiceClient::participantPropertiesEvent(
- std::string &uriString,
-- std::string &alias,
-+ int statusCode,
-+ std::string &statusString,
-+ bool isLocallyMuted,
- bool isModeratorMuted,
- bool isSpeaking,
- int volume,
- F32 energy)
- {
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- participantState *participant = session->findParticipant(uriString);
--
-- if(participant)
-- {
-- participant->mIsSpeaking = isSpeaking;
-- participant->mIsModeratorMuted = isModeratorMuted;
--
-- // SLIM SDK: convert range: ensure that energy is set to zero if is_speaking is false
-- if (isSpeaking)
-- {
-- participant->mSpeakingTimeout.reset();
-- participant->mPower = energy;
-- }
-- else
-- {
-- participant->mPower = 0.0f;
-- }
-- participant->mVolume = volume;
-- }
-- else
-- {
-- LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
-- }
-- }
-- else
-- {
-- LL_INFOS("Voice") << "unknown session " << sessionHandle << LL_ENDL;
-- }
--}
--
--void LLVoiceClient::buddyPresenceEvent(
-- std::string &uriString,
-- std::string &alias,
-- std::string &statusString,
-- std::string &applicationString)
--{
-- buddyListEntry *buddy = findBuddy(uriString);
--
-- if(buddy)
-+ participantState *participant = findParticipant(uriString);
-+ if(participant)
- {
-- LL_DEBUGS("Voice") << "Presence event for " << buddy->mDisplayName << " status \"" << statusString << "\", application \"" << applicationString << "\""<< LL_ENDL;
-- LL_DEBUGS("Voice") << "before: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
--
-- if(applicationString.empty())
-+ participant->mPTT = !isLocallyMuted;
-+ participant->mIsSpeaking = isSpeaking;
-+ participant->mIsModeratorMuted = isModeratorMuted;
-+ if (isSpeaking)
- {
-- // This presence event is from a client that doesn't set up the Application string. Do things the old-skool way.
-- // NOTE: this will be needed to support people who aren't on the 3010-class SDK yet.
--
-- if ( stricmp("Unknown", statusString.c_str())== 0)
-- {
-- // User went offline with a non-SLim-enabled viewer.
-- buddy->mOnlineSL = false;
-- }
-- else if ( stricmp("Online", statusString.c_str())== 0)
-- {
-- // User came online with a non-SLim-enabled viewer.
-- buddy->mOnlineSL = true;
-- }
-- else
-- {
-- // If the user is online through SLim, their status will be "Online-slc", "Away", or something else.
-- // NOTE: we should never see this unless someone is running an OLD version of SLim -- the versions that should be in use now all set the application string.
-- buddy->mOnlineSLim = true;
-- }
-+ participant->mSpeakingTimeout.reset();
- }
-- else if(applicationString.find("SecondLifeViewer") != std::string::npos)
-- {
-- // This presence event is from a viewer that sets the application string
-- if ( stricmp("Unknown", statusString.c_str())== 0)
-- {
-- // Viewer says they're offline
-- buddy->mOnlineSL = false;
-- }
-- else
-- {
-- // Viewer says they're online
-- buddy->mOnlineSL = true;
-- }
-- }
-- else
-- {
-- // This presence event is from something which is NOT the SL viewer (assume it's SLim).
-- if ( stricmp("Unknown", statusString.c_str())== 0)
-- {
-- // SLim says they're offline
-- buddy->mOnlineSLim = false;
-- }
-- else
-- {
-- // SLim says they're online
-- buddy->mOnlineSLim = true;
-- }
-- }
--
-- LL_DEBUGS("Voice") << "after: mOnlineSL = " << (buddy->mOnlineSL?"true":"false") << ", mOnlineSLim = " << (buddy->mOnlineSLim?"true":"false") << LL_ENDL;
--
-- // HACK -- increment the internal change serial number in the LLRelationship (without changing the actual status), so the UI notices the change.
-- LLAvatarTracker::instance().setBuddyOnline(buddy->mUUID,LLAvatarTracker::instance().isBuddyOnline(buddy->mUUID));
--
-- notifyFriendObservers();
-+ participant->mPower = energy;
-+ participant->mVolume = volume;
- }
- else
- {
-- LL_DEBUGS("Voice") << "Presence for unknown buddy " << uriString << LL_ENDL;
-- }
--}
--
--void LLVoiceClient::messageEvent(
-- std::string &sessionHandle,
-- std::string &uriString,
-- std::string &alias,
-- std::string &messageHeader,
-- std::string &messageBody,
-- std::string &applicationString)
--{
-- LL_DEBUGS("Voice") << "Message event, session " << sessionHandle << " from " << uriString << LL_ENDL;
--// LL_DEBUGS("Voice") << " header " << messageHeader << ", body: \n" << messageBody << LL_ENDL;
--
-- if(messageHeader.find("text/html") != std::string::npos)
-- {
-- std::string rawMessage;
--
-- {
-- const std::string startMarker = ", try looking for a instead.
-- start = messageBody.find(startSpan);
-- start = messageBody.find(startMarker2, start);
-- end = messageBody.find(endSpan);
--
-- if(start != std::string::npos)
-- {
-- start += startMarker2.size();
--
-- if(end != std::string::npos)
-- end -= start;
--
-- rawMessage.assign(messageBody, start, end);
-- }
-- }
-- }
--
--// LL_DEBUGS("Voice") << " raw message = \n" << rawMessage << LL_ENDL;
--
-- // strip formatting tags
-- {
-- std::string::size_type start;
-- std::string::size_type end;
--
-- while((start = rawMessage.find('<')) != std::string::npos)
-- {
-- if((end = rawMessage.find('>', start + 1)) != std::string::npos)
-- {
-- // Strip out the tag
-- rawMessage.erase(start, (end + 1) - start);
-- }
-- else
-- {
-- // Avoid an infinite loop
-- break;
-- }
-- }
-- }
--
-- // Decode ampersand-escaped chars
-- {
-- std::string::size_type mark = 0;
--
-- // The text may contain text encoded with <, >, and &
-- mark = 0;
-- while((mark = rawMessage.find("<", mark)) != std::string::npos)
-- {
-- rawMessage.replace(mark, 4, "<");
-- mark += 1;
-- }
--
-- mark = 0;
-- while((mark = rawMessage.find(">", mark)) != std::string::npos)
-- {
-- rawMessage.replace(mark, 4, ">");
-- mark += 1;
-- }
--
-- mark = 0;
-- while((mark = rawMessage.find("&", mark)) != std::string::npos)
-- {
-- rawMessage.replace(mark, 5, "&");
-- mark += 1;
-- }
-- }
--
-- // strip leading/trailing whitespace (since we always seem to get a couple newlines)
-- LLStringUtil::trim(rawMessage);
--
--// LL_DEBUGS("Voice") << " stripped message = \n" << rawMessage << LL_ENDL;
--
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- bool is_busy = gAgent.getBusy();
-- bool is_muted = LLMuteList::getInstance()->isMuted(session->mCallerID, session->mName, LLMute::flagTextChat);
-- bool is_linden = LLMuteList::getInstance()->isLinden(session->mName);
-- bool quiet_chat = false;
-- LLChat chat;
--
-- chat.mMuted = is_muted && !is_linden;
--
-- if(!chat.mMuted)
-- {
-- chat.mFromID = session->mCallerID;
-- chat.mFromName = session->mName;
-- chat.mSourceType = CHAT_SOURCE_AGENT;
--
-- if(is_busy && !is_linden)
-- {
-- quiet_chat = true;
-- // TODO: Question: Return busy mode response here? Or maybe when session is started instead?
-- }
--
-- std::string fullMessage = std::string(": ") + rawMessage;
--
-- LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
-- gIMMgr->addMessage(session->mIMSessionID,
-- session->mCallerID,
-- session->mName.c_str(),
-- fullMessage.c_str(),
-- LLStringUtil::null, // default arg
-- IM_NOTHING_SPECIAL, // default arg
-- 0, // default arg
-- LLUUID::null, // default arg
-- LLVector3::zero, // default arg
-- true); // prepend name and make it a link to the user's profile
--
-- chat.mText = std::string("IM: ") + session->mName + std::string(": ") + rawMessage;
-- // If the chat should come in quietly (i.e. we're in busy mode), pretend it's from a local agent.
-- LLFloaterChat::addChat( chat, TRUE, quiet_chat );
-- }
-- }
-- }
--}
--
--void LLVoiceClient::sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string ¬ificationType)
--{
-- sessionState *session = findSession(sessionHandle);
--
-- if(session)
-- {
-- participantState *participant = session->findParticipant(uriString);
-- if(participant)
-- {
-- if (!stricmp(notificationType.c_str(), "Typing"))
-- {
-- // Other end started typing
-- // TODO: The proper way to add a typing notification seems to be LLIMMgr::processIMTypingStart().
-- // It requires an LLIMInfo for the message, which we don't have here.
-- }
-- else if (!stricmp(notificationType.c_str(), "NotTyping"))
-- {
-- // Other end stopped typing
-- // TODO: The proper way to remove a typing notification seems to be LLIMMgr::processIMTypingStop().
-- // It requires an LLIMInfo for the message, which we don't have here.
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Unknown notification type " << notificationType << "for participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
-- }
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Unknown participant " << uriString << " in session " << session->mSIPURI << LL_ENDL;
-- }
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Unknown session handle " << sessionHandle << LL_ENDL;
-- }
--}
--
--void LLVoiceClient::subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType)
--{
-- buddyListEntry *buddy = findBuddy(buddyURI);
--
-- if(!buddy)
-- {
-- // Couldn't find buddy by URI, try converting the alias...
-- if(!alias.empty())
-- {
-- LLUUID id;
-- if(IDFromName(alias, id))
-- {
-- buddy = findBuddy(id);
-- }
-- }
-- }
--
-- if(buddy)
-- {
-- std::ostringstream stream;
--
-- if(buddy->mCanSeeMeOnline)
-- {
-- // Sending the response will create an auto-accept rule
-- buddy->mHasAutoAcceptListEntry = true;
-- }
-- else
-- {
-- // Sending the response will create a block rule
-- buddy->mHasBlockListEntry = true;
-- }
--
-- if(buddy->mInSLFriends)
-- {
-- buddy->mInVivoxBuddies = true;
-- }
--
-- stream
-- << ""
-- << "" << mAccountHandle << ""
-- << "" << buddy->mURI << ""
-- << "" << (buddy->mCanSeeMeOnline?"Allow":"Hide") << ""
-- << ""<< (buddy->mInSLFriends?"1":"0")<< ""
-- << "" << subscriptionHandle << ""
-- << ""
-- << "\n\n\n";
--
-- writeString(stream.str());
-+ LL_WARNS("Voice") << "unknown participant: " << uriString << LL_ENDL;
- }
- }
-
-@@ -4708,226 +3038,155 @@ void LLVoiceClient::auxAudioPropertiesEvent(F32 energy)
- mTuningEnergy = energy;
- }
-
--void LLVoiceClient::buddyListChanged()
--{
-- // This is called after we receive a BuddyAndGroupListChangedEvent.
-- mBuddyListMapPopulated = true;
-- mFriendsListDirty = true;
--}
--
- void LLVoiceClient::muteListChanged()
- {
- // The user's mute list has been updated. Go through the current participant list and sync it with the mute list.
-- if(mAudioSession)
-- {
-- participantMap::iterator iter = mAudioSession->mParticipantsByURI.begin();
--
-- for(; iter != mAudioSession->mParticipantsByURI.end(); iter++)
-- {
-- participantState *p = iter->second;
--
-- // Check to see if this participant is on the mute list already
-- if(p->updateMuteState())
-- mAudioSession->mVolumeDirty = true;
-- }
-- }
--}
-
--void LLVoiceClient::updateFriends(U32 mask)
--{
-- if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::POWERS))
-+ participantMap::iterator iter = mParticipantMap.begin();
-+
-+ for(; iter != mParticipantMap.end(); iter++)
- {
-- // Just resend the whole friend list to the daemon
-- mFriendsListDirty = true;
-+ participantState *p = iter->second;
-+
-+ // Check to see if this participant is on the mute list already
-+ updateMuteState(p);
- }
- }
-
- /////////////////////////////
- // Managing list of participants
- LLVoiceClient::participantState::participantState(const std::string &uri) :
-- mURI(uri),
-- mPTT(false),
-- mIsSpeaking(false),
-- mIsModeratorMuted(false),
-- mLastSpokeTimestamp(0.f),
-- mPower(0.f),
-- mVolume(0),
-- mOnMuteList(false),
-- mUserVolume(100),
-- mVolumeDirty(false),
-- mAvatarIDValid(false),
-- mIsSelf(false)
-+ mURI(uri), mPTT(false), mIsSpeaking(false), mIsModeratorMuted(false), mLastSpokeTimestamp(0.f), mPower(0.f), mVolume(0), mServiceType(serviceTypeUnknown),
-+ mOnMuteList(false), mUserVolume(100), mVolumeDirty(false), mAvatarIDValid(false)
- {
- }
-
--LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(const std::string &uri)
-+LLVoiceClient::participantState *LLVoiceClient::addParticipant(const std::string &uri)
- {
- participantState *result = NULL;
-- bool useAlternateURI = false;
-+
-+ participantMap::iterator iter = mParticipantMap.find(uri);
-
-- // Note: this is mostly the body of LLVoiceClient::sessionState::findParticipant(), but since we need to know if it
-- // matched the alternate SIP URI (so we can add it properly), we need to reproduce it here.
-+ if(iter != mParticipantMap.end())
- {
-- participantMap::iterator iter = mParticipantsByURI.find(&uri);
--
-- if(iter == mParticipantsByURI.end())
-- {
-- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
-- {
-- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
-- // Use mSIPURI instead, since it will be properly encoded.
-- iter = mParticipantsByURI.find(&(mSIPURI));
-- useAlternateURI = true;
-- }
-- }
--
-- if(iter != mParticipantsByURI.end())
-- {
-- result = iter->second;
-- }
-+ // Found a matching participant already in the map.
-+ result = iter->second;
- }
--
-+
- if(!result)
- {
- // participant isn't already in one list or the other.
-- result = new participantState(useAlternateURI?mSIPURI:uri);
-- mParticipantsByURI.insert(participantMap::value_type(&(result->mURI), result));
-- mParticipantsChanged = true;
-+ result = new participantState(uri);
-+ mParticipantMap.insert(participantMap::value_type(uri, result));
-+ mParticipantMapChanged = true;
-
- // Try to do a reverse transform on the URI to get the GUID back.
- {
- LLUUID id;
-- if(IDFromName(result->mURI, id))
-+ if(IDFromName(uri, id))
- {
- result->mAvatarIDValid = true;
- result->mAvatarID = id;
-
-- if(result->updateMuteState())
-- mVolumeDirty = true;
-- }
-- else
-- {
-- // 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);
-+ updateMuteState(result);
- }
- }
-
-- mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result));
--
- LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL;
- }
-
- return result;
- }
-
--bool LLVoiceClient::participantState::updateMuteState()
-+void LLVoiceClient::updateMuteState(participantState *p)
- {
-- bool result = false;
--
-- if(mAvatarIDValid)
-+ if(p->mAvatarIDValid)
- {
-- bool isMuted = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
-- if(mOnMuteList != isMuted)
-+ bool isMuted = LLMuteList::getInstance()->isMuted(p->mAvatarID, LLMute::flagVoiceChat);
-+ if(p->mOnMuteList != isMuted)
- {
-- mOnMuteList = isMuted;
-+ p->mOnMuteList = isMuted;
-+ p->mVolumeDirty = true;
- mVolumeDirty = true;
-- result = true;
- }
- }
-- return result;
- }
-
--void LLVoiceClient::sessionState::removeParticipant(LLVoiceClient::participantState *participant)
-+void LLVoiceClient::removeParticipant(LLVoiceClient::participantState *participant)
- {
- if(participant)
- {
-- participantMap::iterator iter = mParticipantsByURI.find(&(participant->mURI));
-- participantUUIDMap::iterator iter2 = mParticipantsByUUID.find(&(participant->mAvatarID));
--
-+ participantMap::iterator iter = mParticipantMap.find(participant->mURI);
-+
- LL_DEBUGS("Voice") << "participant \"" << participant->mURI << "\" (" << participant->mAvatarID << ") removed." << LL_ENDL;
--
-- if(iter == mParticipantsByURI.end())
-- {
-- LL_ERRS("Voice") << "Internal error: participant " << participant->mURI << " not in URI map" << LL_ENDL;
-- }
-- else if(iter2 == mParticipantsByUUID.end())
-- {
-- LL_ERRS("Voice") << "Internal error: participant ID " << participant->mAvatarID << " not in UUID map" << LL_ENDL;
-- }
-- else if(iter->second != iter2->second)
-- {
-- LL_ERRS("Voice") << "Internal error: participant mismatch!" << LL_ENDL;
-- }
-- else
-- {
-- mParticipantsByURI.erase(iter);
-- mParticipantsByUUID.erase(iter2);
--
-- delete participant;
-- mParticipantsChanged = true;
-- }
-+
-+ mParticipantMap.erase(iter);
-+ delete participant;
-+ mParticipantMapChanged = true;
- }
- }
-
--void LLVoiceClient::sessionState::removeAllParticipants()
-+void LLVoiceClient::removeAllParticipants()
- {
- LL_DEBUGS("Voice") << "called" << LL_ENDL;
-
-- while(!mParticipantsByURI.empty())
-+ while(!mParticipantMap.empty())
- {
-- removeParticipant(mParticipantsByURI.begin()->second);
-- }
--
-- if(!mParticipantsByUUID.empty())
-- {
-- LL_ERRS("Voice") << "Internal error: empty URI map, non-empty UUID map" << LL_ENDL
-+ removeParticipant(mParticipantMap.begin()->second);
- }
- }
-
- LLVoiceClient::participantMap *LLVoiceClient::getParticipantList(void)
- {
-- participantMap *result = NULL;
-- if(mAudioSession)
-- {
-- result = &(mAudioSession->mParticipantsByURI);
-- }
-- return result;
-+ return &mParticipantMap;
- }
-
-
--LLVoiceClient::participantState *LLVoiceClient::sessionState::findParticipant(const std::string &uri)
-+LLVoiceClient::participantState *LLVoiceClient::findParticipant(const std::string &uri)
- {
- participantState *result = NULL;
-
-- participantMap::iterator iter = mParticipantsByURI.find(&uri);
--
-- if(iter == mParticipantsByURI.end())
-+ // Don't find any participants if we're not connected. This is so that we don't continue to get stale data
-+ // after the daemon dies.
-+ if(mConnected)
- {
-- if(!mAlternateSIPURI.empty() && (uri == mAlternateSIPURI))
-+ participantMap::iterator iter = mParticipantMap.find(uri);
-+
-+ if(iter != mParticipantMap.end())
- {
-- // This is a p2p session (probably with the SLIM client) with an alternate URI for the other participant.
-- // Look up the other URI
-- iter = mParticipantsByURI.find(&(mSIPURI));
-+ result = iter->second;
- }
- }
--
-- if(iter != mParticipantsByURI.end())
-- {
-- result = iter->second;
-- }
--
-+
- return result;
- }
-
--LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByID(const LLUUID& id)
-+
-+LLVoiceClient::participantState *LLVoiceClient::findParticipantByAvatar(LLVOAvatar *avatar)
- {
- participantState * result = NULL;
-- participantUUIDMap::iterator iter = mParticipantsByUUID.find(&id);
-
-- if(iter != mParticipantsByUUID.end())
-+ // You'd think this would work, but it doesn't...
-+// std::string uri = sipURIFromAvatar(avatar);
-+
-+ // Currently, the URI is just the account name.
-+ std::string loginName = nameFromAvatar(avatar);
-+ result = findParticipant(loginName);
-+
-+ if(result != NULL)
- {
-- result = iter->second;
-+ if(!result->mAvatarIDValid)
-+ {
-+ result->mAvatarID = avatar->getID();
-+ result->mAvatarIDValid = true;
-+
-+ // We just figured out the avatar ID, so the participant list has "changed" from the perspective of anyone who uses that to identify participants.
-+ mParticipantMapChanged = true;
-+
-+ updateMuteState(result);
-+ }
-+
-+
- }
-
- return result;
-@@ -4936,19 +3195,43 @@ LLVoiceClient::participantState* LLVoiceClient::sessionState::findParticipantByI
- LLVoiceClient::participantState* LLVoiceClient::findParticipantByID(const LLUUID& id)
- {
- participantState * result = NULL;
-+
-+ // Currently, the URI is just the account name.
-+ std::string loginName = nameFromID(id);
-+ result = findParticipant(loginName);
-+
-+ return result;
-+}
-+
-+
-+void LLVoiceClient::clearChannelMap(void)
-+{
-+ mChannelMap.clear();
-+}
-+
-+void LLVoiceClient::addChannelMapEntry(std::string &name, std::string &uri)
-+{
-+ LL_DEBUGS("Voice") << "Adding channel name mapping: " << name << " -> " << uri << LL_ENDL;
-+ mChannelMap.insert(channelMap::value_type(name, uri));
-+}
-+
-+std::string LLVoiceClient::findChannelURI(std::string &name)
-+{
-+ std::string result;
-
-- if(mAudioSession)
-+ channelMap::iterator iter = mChannelMap.find(name);
-+
-+ if(iter != mChannelMap.end())
- {
-- result = mAudioSession->findParticipantByID(id);
-+ result = iter->second;
- }
-
- return result;
- }
-
--
- void LLVoiceClient::parcelChanged()
- {
-- if(getState() >= stateNoChannel)
-+ if(getState() >= stateLoggedIn)
- {
- // If the user is logged in, start a channel lookup.
- LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
-@@ -4962,7 +3245,7 @@ void LLVoiceClient::parcelChanged()
- }
- else
- {
-- // The transition to stateNoChannel needs to kick this off again.
-+ // The transition to stateLoggedIn needs to kick this off again.
- LL_INFOS("Voice") << "not logged in yet, deferring" << LL_ENDL;
- }
- }
-@@ -4970,17 +3253,12 @@ void LLVoiceClient::parcelChanged()
- void LLVoiceClient::switchChannel(
- std::string uri,
- bool spatial,
-- bool no_reconnect,
-- bool is_p2p,
-+ bool noReconnect,
- std::string hash)
- {
- bool needsSwitch = false;
-
-- LL_DEBUGS("Voice")
-- << "called in state " << state2string(getState())
-- << " with uri \"" << uri << "\""
-- << (spatial?", spatial is true":", spatial is false")
-- << LL_ENDL;
-+ LL_DEBUGS("Voice") << "called in state " << state2string(getState()) << " with uri \"" << uri << "\"" << LL_ENDL;
-
- switch(getState())
- {
-@@ -4990,18 +3268,18 @@ void LLVoiceClient::switchChannel(
- // Always switch to the new URI from these states.
- needsSwitch = true;
- break;
--
-+
- default:
- if(mSessionTerminateRequested)
- {
- // If a terminate has been requested, we need to compare against where the URI we're already headed to.
-- if(mNextAudioSession && (mNextAudioSession->mSIPURI != uri))
-+ if(mNextSessionURI != uri)
- needsSwitch = true;
- }
- else
- {
- // Otherwise, compare against the URI we're in now.
-- if(mAudioSession && (mAudioSession->mSIPURI != uri))
-+ if(mSessionURI != uri)
- needsSwitch = true;
- }
- break;
-@@ -5009,28 +3287,22 @@ void LLVoiceClient::switchChannel(
-
- if(needsSwitch)
- {
-+ mNextSessionURI = uri;
-+ mNextSessionHash = hash;
-+ mNextSessionHandle.clear();
-+ mNextP2PSessionURI.clear();
-+ mNextSessionSpatial = spatial;
-+ mNextSessionNoReconnect = noReconnect;
-+
- if(uri.empty())
- {
- // Leave any channel we may be in
- LL_DEBUGS("Voice") << "leaving channel" << LL_ENDL;
--
-- sessionState *oldSession = mNextAudioSession;
-- mNextAudioSession = NULL;
--
-- // The old session may now need to be deleted.
-- reapSession(oldSession);
--
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
- }
- else
- {
- LL_DEBUGS("Voice") << "switching to channel " << uri << LL_ENDL;
--
-- mNextAudioSession = addSession(uri);
-- mNextAudioSession->mHash = hash;
-- mNextAudioSession->mIsSpatial = spatial;
-- mNextAudioSession->mReconnect = !no_reconnect;
-- mNextAudioSession->mIsP2P = is_p2p;
- }
-
- if(getState() <= stateNoChannel)
-@@ -5045,10 +3317,15 @@ void LLVoiceClient::switchChannel(
- }
- }
-
--void LLVoiceClient::joinSession(sessionState *session)
-+void LLVoiceClient::joinSession(std::string handle, std::string uri)
- {
-- mNextAudioSession = session;
--
-+ mNextSessionURI.clear();
-+ mNextSessionHash.clear();
-+ mNextP2PSessionURI = uri;
-+ mNextSessionHandle = handle;
-+ mNextSessionSpatial = false;
-+ mNextSessionNoReconnect = false;
-+
- if(getState() <= stateNoChannel)
- {
- // We're already set up to join a channel, just needed to fill in the session handle
-@@ -5064,7 +3341,7 @@ void LLVoiceClient::setNonSpatialChannel(
- const std::string &uri,
- const std::string &credentials)
- {
-- switchChannel(uri, false, false, false, credentials);
-+ switchChannel(uri, false, false, credentials);
- }
-
- void LLVoiceClient::setSpatialChannel(
-@@ -5072,216 +3349,51 @@ void LLVoiceClient::setSpatialChannel(
- const std::string &credentials)
- {
- mSpatialSessionURI = uri;
-- mSpatialSessionCredentials = credentials;
- mAreaVoiceDisabled = mSpatialSessionURI.empty();
-
- LL_DEBUGS("Voice") << "got spatial channel uri: \"" << uri << "\"" << LL_ENDL;
-
-- if((mAudioSession && !(mAudioSession->mIsSpatial)) || (mNextAudioSession && !(mNextAudioSession->mIsSpatial)))
-+ if(mNonSpatialChannel || !mNextSessionSpatial)
- {
- // User is in a non-spatial chat or joining a non-spatial chat. Don't switch channels.
- LL_INFOS("Voice") << "in non-spatial chat, not switching channels" << LL_ENDL;
- }
- else
- {
-- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
-+ switchChannel(mSpatialSessionURI, true, false, credentials);
- }
- }
-
--void LLVoiceClient::callUser(const LLUUID &uuid)
-+void LLVoiceClient::callUser(LLUUID &uuid)
- {
- std::string userURI = sipURIFromID(uuid);
-
-- switchChannel(userURI, false, true, true);
--}
--
--LLVoiceClient::sessionState* LLVoiceClient::startUserIMSession(const LLUUID &uuid)
--{
-- // Figure out if a session with the user already exists
-- sessionState *session = findSession(uuid);
-- if(!session)
-- {
-- // No session with user, need to start one.
-- std::string uri = sipURIFromID(uuid);
-- session = addSession(uri);
-- session->mIsSpatial = false;
-- session->mReconnect = false;
-- session->mIsP2P = true;
-- session->mCallerID = uuid;
-- }
--
-- if(session)
-- {
-- if(session->mHandle.empty())
-- {
-- // Session isn't active -- start it up.
-- sessionCreateSendMessage(session, false, true);
-- }
-- else
-- {
-- // Session is already active -- start up text.
-- sessionTextConnectSendMessage(session);
-- }
-- }
--
-- return session;
--}
--
--bool LLVoiceClient::sendTextMessage(const LLUUID& participant_id, const std::string& message)
--{
-- bool result = false;
--
-- // Attempt to locate the indicated session
-- sessionState *session = startUserIMSession(participant_id);
-- if(session)
-- {
-- // found the session, attempt to send the message
-- session->mTextMsgQueue.push(message);
--
-- // Try to send queued messages (will do nothing if the session is not open yet)
-- sendQueuedTextMessages(session);
--
-- // The message is queued, so we succeed.
-- result = true;
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Session not found for participant ID " << participant_id << LL_ENDL;
-- }
--
-- return result;
--}
--
--void LLVoiceClient::sendQueuedTextMessages(sessionState *session)
--{
-- if(session->mTextStreamState == 1)
-- {
-- if(!session->mTextMsgQueue.empty())
-- {
-- std::ostringstream stream;
--
-- while(!session->mTextMsgQueue.empty())
-- {
-- std::string message = session->mTextMsgQueue.front();
-- session->mTextMsgQueue.pop();
-- stream
-- << ""
-- << "" << session->mHandle << ""
-- << "text/HTML"
-- << "" << message << ""
-- << ""
-- << "\n\n\n";
-- }
-- writeString(stream.str());
-- }
-- }
-- else
-- {
-- // Session isn't connected yet, defer until later.
-- }
--}
--
--void LLVoiceClient::endUserIMSession(const LLUUID &uuid)
--{
-- // Figure out if a session with the user exists
-- sessionState *session = findSession(uuid);
-- if(session)
-- {
-- // found the session
-- if(!session->mHandle.empty())
-- {
-- sessionTextDisconnectSendMessage(session);
-- }
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Session not found for participant ID " << uuid << LL_ENDL;
-- }
-+ switchChannel(userURI, false, true);
- }
-
--bool LLVoiceClient::answerInvite(std::string &sessionHandle)
-+void LLVoiceClient::answerInvite(std::string &sessionHandle, LLUUID& other_user_id)
- {
-- // this is only ever used to answer incoming p2p call invites.
--
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- session->mIsSpatial = false;
-- session->mReconnect = false;
-- session->mIsP2P = true;
--
-- joinSession(session);
-- return true;
-- }
--
-- return false;
--}
--
--bool LLVoiceClient::isOnlineSIP(const LLUUID &id)
--{
-- bool result = false;
-- buddyListEntry *buddy = findBuddy(id);
-- if(buddy)
-- {
-- result = buddy->mOnlineSLim;
-- LL_DEBUGS("Voice") << "Buddy " << buddy->mDisplayName << " is SIP " << (result?"online":"offline") << LL_ENDL;
-- }
--
-- if(!result)
-- {
-- // This user isn't on the buddy list or doesn't show online status through the buddy list, but could be a participant in an existing session if they initiated a text IM.
-- sessionState *session = findSession(id);
-- if(session && !session->mHandle.empty())
-- {
-- if((session->mTextStreamState != streamStateUnknown) || (session->mMediaStreamState > streamStateIdle))
-- {
-- LL_DEBUGS("Voice") << "Open session with " << id << " found, returning SIP online state" << LL_ENDL;
-- // we have a p2p text session open with this user, so by definition they're online.
-- result = true;
-- }
-- }
-- }
--
-- return result;
-+ joinSession(sessionHandle, sipURIFromID(other_user_id));
- }
-
- void LLVoiceClient::declineInvite(std::string &sessionHandle)
- {
-- sessionState *session = findSession(sessionHandle);
-- if(session)
-- {
-- sessionMediaDisconnectSendMessage(session);
-- }
-+ sessionTerminateByHandle(sessionHandle);
- }
-
- void LLVoiceClient::leaveNonSpatialChannel()
- {
-- LL_DEBUGS("Voice")
-- << "called in state " << state2string(getState())
-- << LL_ENDL;
--
-- // Make sure we don't rejoin the current session.
-- sessionState *oldNextSession = mNextAudioSession;
-- mNextAudioSession = NULL;
--
-- // Most likely this will still be the current session at this point, but check it anyway.
-- reapSession(oldNextSession);
--
-- verifySessionState();
--
-- sessionTerminate();
-+ switchChannel(mSpatialSessionURI);
- }
-
- std::string LLVoiceClient::getCurrentChannel()
- {
-- std::string result;
--
- if((getState() == stateRunning) && !mSessionTerminateRequested)
- {
-- result = getAudioSessionURI();
-+ return mSessionURI;
- }
-
-- return result;
-+ return "";
- }
-
- bool LLVoiceClient::inProximalChannel()
-@@ -5290,7 +3402,7 @@ bool LLVoiceClient::inProximalChannel()
-
- if((getState() == stateRunning) && !mSessionTerminateRequested)
- {
-- result = inSpatialChannel();
-+ result = !mNonSpatialChannel;
- }
-
- return result;
-@@ -5302,7 +3414,7 @@ std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
- result = "sip:";
- result += nameFromID(id);
- result += "@";
-- result += mVoiceSIPURIHostName;
-+ result += mAccountServerName;
-
- return result;
- }
-@@ -5315,7 +3427,7 @@ std::string LLVoiceClient::sipURIFromAvatar(LLVOAvatar *avatar)
- result = "sip:";
- result += nameFromID(avatar->getID());
- result += "@";
-- result += mVoiceSIPURIHostName;
-+ result += mAccountServerName;
- }
-
- return result;
-@@ -5334,13 +3446,6 @@ std::string LLVoiceClient::nameFromAvatar(LLVOAvatar *avatar)
- std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
- {
- std::string result;
--
-- if (uuid.isNull()) {
-- //VIVOX, the uuid emtpy look for the mURIString and return that instead.
-- //result.assign(uuid.mURIStringName);
-- LLStringUtil::replaceChar(result, '_', ' ');
-- return result;
-- }
- // Prepending this apparently prevents conflicts with reserved names inside the vivox and diamondware code.
- result = "x";
-
-@@ -5354,24 +3459,13 @@ std::string LLVoiceClient::nameFromID(const LLUUID &uuid)
- // If you need to transform a GUID to this form on the Mac OS X command line, this will do so:
- // echo -n x && (echo e669132a-6c43-4ee1-a78d-6c82fff59f32 |xxd -r -p |openssl base64|tr '/+' '_-')
-
-- // The reverse transform can be done with:
-- // echo 'x5mkTKmxDTuGnjWyC__WfMg==' |cut -b 2- -|tr '_-' '/+' |openssl base64 -d|xxd -p
--
- return result;
- }
-
--bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
-+bool LLVoiceClient::IDFromName(const std::string name, LLUUID &uuid)
- {
- bool result = false;
-
-- // SLIM SDK: The "name" may actually be a SIP URI such as: "sip:xFnPP04IpREWNkuw1cOXlhw==@bhr.vivox.com"
-- // If it is, convert to a bare name before doing the transform.
-- std::string name = nameFromsipURI(inName);
--
-- // Doesn't look like a SIP URI, assume it's an actual name.
-- if(name.empty())
-- name = inName;
--
- // This will only work if the name is of the proper form.
- // As an example, the account name for Monroe Linden (UUID 1673cfd3-8229-4445-8d92-ec3570e5e587) is:
- // "xFnPP04IpREWNkuw1cOXlhw=="
-@@ -5393,13 +3487,6 @@ bool LLVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
- memcpy(uuid.mData, rawuuid, UUID_BYTES);
- result = true;
- }
-- }
--
-- if(!result)
-- {
-- // VIVOX: not a standard account name, just copy the URI name mURIString field
-- // and hope for the best. bpj
-- uuid.setNull(); // VIVOX, set the uuid field to nulls
- }
-
- return result;
-@@ -5416,59 +3503,13 @@ std::string LLVoiceClient::sipURIFromName(std::string &name)
- result = "sip:";
- result += name;
- result += "@";
-- result += mVoiceSIPURIHostName;
-+ result += mAccountServerName;
-
- // LLStringUtil::toLower(result);
-
- return result;
- }
-
--std::string LLVoiceClient::nameFromsipURI(const std::string &uri)
--{
-- std::string result;
--
-- std::string::size_type sipOffset, atOffset;
-- sipOffset = uri.find("sip:");
-- atOffset = uri.find("@");
-- if((sipOffset != std::string::npos) && (atOffset != std::string::npos))
-- {
-- result = uri.substr(sipOffset + 4, atOffset - (sipOffset + 4));
-- }
--
-- return result;
--}
--
--bool LLVoiceClient::inSpatialChannel(void)
--{
-- bool result = false;
--
-- if(mAudioSession)
-- result = mAudioSession->mIsSpatial;
--
-- return result;
--}
--
--std::string LLVoiceClient::getAudioSessionURI()
--{
-- std::string result;
--
-- if(mAudioSession)
-- result = mAudioSession->mSIPURI;
--
-- return result;
--}
--
--std::string LLVoiceClient::getAudioSessionHandle()
--{
-- std::string result;
--
-- if(mAudioSession)
-- result = mAudioSession->mHandle;
--
-- return result;
--}
--
--
- /////////////////////////////
- // Sending updates of current state
-
-@@ -5507,8 +3548,7 @@ void LLVoiceClient::updatePosition(void)
- LLMatrix3 rot;
- LLVector3d pos;
-
-- // TODO: If camera and avatar velocity are actually used by the voice system, we could compute them here...
-- // They're currently always set to zero.
-+ // MBW -- XXX -- Setting both camera and avatar velocity to 0 for now. May figure it out later...
-
- // Send the current camera position to the voice code
- rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (), LLViewerCamera::getInstance()->getUpAxis());
-@@ -5523,7 +3563,7 @@ void LLVoiceClient::updatePosition(void)
- rot = agent->getRootJoint()->getWorldRotation().getMatrix3();
-
- pos = agent->getPositionGlobal();
-- // TODO: Can we get the head offset from outside the LLVOAvatar?
-+ // MBW -- XXX -- Can we get the head offset from outside the LLVOAvatar?
- // pos += LLVector3d(mHeadOffset);
- pos += LLVector3d(0.f, 0.f, 1.f);
-
-@@ -5629,8 +3669,8 @@ void LLVoiceClient::setVoiceEnabled(bool enabled)
- }
- else
- {
-- // Turning voice off looses your current channel -- this makes sure the UI isn't out of sync when you re-enable it.
-- LLVoiceChannel::getCurrentVoiceChannel()->deactivate();
-+ // for now, leave active channel, to auto join when turning voice back on
-+ //LLVoiceChannel::getCurrentVoiceChannel->deactivate();
- }
- }
- }
-@@ -5710,34 +3750,56 @@ void LLVoiceClient::setEarLocation(S32 loc)
-
- void LLVoiceClient::setVoiceVolume(F32 volume)
- {
-- int scaled_volume = scale_speaker_volume(volume);
-+ LL_DEBUGS("Voice") << "volume is " << volume << LL_ENDL;
-
-- if(scaled_volume != mSpeakerVolume)
-+ // incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
-+ // Map it as follows: 0.0 -> -100, 0.5 -> 24, 1.0 -> 50
-+
-+ volume -= 0.5f; // offset volume to the range [-0.5 ... 0.5], with 0 at the default.
-+ int scaledVolume = 24; // offset scaledVolume by its default level
-+ if(volume < 0.0f)
-+ scaledVolume += ((int)(volume * 248.0f)); // (24 - (-100)) * 2
-+ else
-+ scaledVolume += ((int)(volume * 52.0f)); // (50 - 24) * 2
-+
-+ if(scaledVolume != mSpeakerVolume)
- {
-- if((scaled_volume == 0) || (mSpeakerVolume == 0))
-+ if((scaledVolume == -100) || (mSpeakerVolume == -100))
- {
- mSpeakerMuteDirty = true;
- }
-
-- mSpeakerVolume = scaled_volume;
-+ mSpeakerVolume = scaledVolume;
- mSpeakerVolumeDirty = true;
- }
- }
-
- void LLVoiceClient::setMicGain(F32 volume)
- {
-- int scaled_volume = scale_mic_volume(volume);
--
-- if(scaled_volume != mMicVolume)
-+ int scaledVolume = ((int)(volume * 100.0f)) - 100;
-+ if(scaledVolume != mMicVolume)
- {
-- mMicVolume = scaled_volume;
-+ mMicVolume = scaledVolume;
- mMicVolumeDirty = true;
- }
- }
-
-+void LLVoiceClient::setVivoxDebugServerName(std::string &serverName)
-+{
-+ if(!mAccountServerName.empty())
-+ {
-+ // The name has been filled in already, which means we know whether we're connecting to agni or not.
-+ if(!sConnectingToAgni)
-+ {
-+ // Only use the setting if we're connecting to a development grid -- always use bhr when on agni.
-+ mAccountServerName = serverName;
-+ }
-+ }
-+}
-+
- void LLVoiceClient::keyDown(KEY key, MASK mask)
- {
--// LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
-+ LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL;
-
- if (gKeyboard->getKeyRepeated(key))
- {
-@@ -5875,6 +3937,19 @@ BOOL LLVoiceClient::getUsingPTT(const LLUUID& id)
- return result;
- }
-
-+BOOL LLVoiceClient::getPTTPressed(const LLUUID& id)
-+{
-+ BOOL result = FALSE;
-+
-+ participantState *participant = findParticipantByID(id);
-+ if(participant)
-+ {
-+ result = participant->mPTT;
-+ }
-+
-+ return result;
-+}
-+
- BOOL LLVoiceClient::getOnMuteList(const LLUUID& id)
- {
- BOOL result = FALSE;
-@@ -5906,841 +3981,144 @@ F32 LLVoiceClient::getUserVolume(const LLUUID& id)
-
- void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume)
- {
-- if(mAudioSession)
-- {
-- participantState *participant = findParticipantByID(id);
-- if (participant)
-- {
-- // volume can amplify by as much as 4x!
-- S32 ivol = (S32)(400.f * volume * volume);
-- participant->mUserVolume = llclamp(ivol, 0, 400);
-- participant->mVolumeDirty = TRUE;
-- mAudioSession->mVolumeDirty = TRUE;
-- }
-- }
--}
--
--std::string LLVoiceClient::getGroupID(const LLUUID& id)
--{
-- std::string result;
--
- participantState *participant = findParticipantByID(id);
-- if(participant)
-+ if (participant)
- {
-- result = participant->mGroupID;
-+ // volume can amplify by as much as 4x!
-+ S32 ivol = (S32)(400.f * volume * volume);
-+ participant->mUserVolume = llclamp(ivol, 0, 400);
-+ participant->mVolumeDirty = TRUE;
-+ mVolumeDirty = TRUE;
- }
--
-- return result;
- }
-
--BOOL LLVoiceClient::getAreaVoiceDisabled()
--{
-- return mAreaVoiceDisabled;
--}
--
--void LLVoiceClient::recordingLoopStart(int seconds, int deltaFramesPerControlFrame)
--{
--// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Start)" << LL_ENDL;
--
-- if(!mMainSessionGroupHandle.empty())
-- {
-- std::ostringstream stream;
-- stream
-- << ""
-- << "" << mMainSessionGroupHandle << ""
-- << "Start"
-- << "" << deltaFramesPerControlFrame << ""
-- << "" << "" << ""
-- << "false"
-- << "" << seconds << ""
-- << "\n\n\n";
-
-
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::recordingLoopSave(const std::string& filename)
-+LLVoiceClient::serviceType LLVoiceClient::getServiceType(const LLUUID& id)
- {
--// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Flush)" << LL_ENDL;
-+ serviceType result = serviceTypeUnknown;
-
-- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-- {
-- std::ostringstream stream;
-- stream
-- << ""
-- << "" << mMainSessionGroupHandle << ""
-- << "Flush"
-- << "" << filename << ""
-- << "\n\n\n";
--
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::recordingStop()
--{
--// LL_DEBUGS("Voice") << "sending SessionGroup.ControlRecording (Stop)" << LL_ENDL;
--
-- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-- {
-- std::ostringstream stream;
-- stream
-- << ""
-- << "" << mMainSessionGroupHandle << ""
-- << "Stop"
-- << "\n\n\n";
--
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::filePlaybackStart(const std::string& filename)
--{
--// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Start)" << LL_ENDL;
--
-- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-- {
-- std::ostringstream stream;
-- stream
-- << ""
-- << "" << mMainSessionGroupHandle << ""
-- << "Start"
-- << "" << filename << ""
-- << "\n\n\n";
--
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::filePlaybackStop()
--{
--// LL_DEBUGS("Voice") << "sending SessionGroup.ControlPlayback (Stop)" << LL_ENDL;
--
-- if(mAudioSession != NULL && !mAudioSession->mGroupHandle.empty())
-- {
-- std::ostringstream stream;
-- stream
-- << ""
-- << "" << mMainSessionGroupHandle << ""
-- << "Stop"
-- << "\n\n\n";
--
-- writeString(stream.str());
-- }
--}
--
--void LLVoiceClient::filePlaybackSetPaused(bool paused)
--{
-- // TODO: Implement once Vivox gives me a sample
--}
--
--void LLVoiceClient::filePlaybackSetMode(bool vox, float speed)
--{
-- // TODO: Implement once Vivox gives me a sample
--}
--
--LLVoiceClient::sessionState::sessionState() :
-- mMediaStreamState(streamStateUnknown),
-- mTextStreamState(streamStateUnknown),
-- mCreateInProgress(false),
-- mMediaConnectInProgress(false),
-- mVoiceInvitePending(false),
-- mTextInvitePending(false),
-- mSynthesizedCallerID(false),
-- mIsChannel(false),
-- mIsSpatial(false),
-- mIsP2P(false),
-- mIncoming(false),
-- mVoiceEnabled(false),
-- mReconnect(false),
-- mVolumeDirty(false),
-- mParticipantsChanged(false)
--{
--}
--
--LLVoiceClient::sessionState::~sessionState()
--{
-- removeAllParticipants();
--}
--
--LLVoiceClient::sessionIterator LLVoiceClient::sessionsBegin(void)
--{
-- return mSessions.begin();
--}
--
--LLVoiceClient::sessionIterator LLVoiceClient::sessionsEnd(void)
--{
-- return mSessions.end();
--}
--
--
--LLVoiceClient::sessionState *LLVoiceClient::findSession(const std::string &handle)
--{
-- sessionState *result = NULL;
-- sessionMap::iterator iter = mSessionsByHandle.find(&handle);
-- if(iter != mSessionsByHandle.end())
-- {
-- result = iter->second;
-- }
--
-- return result;
--}
--
--LLVoiceClient::sessionState *LLVoiceClient::findSessionBeingCreatedByURI(const std::string &uri)
--{
-- sessionState *result = NULL;
-- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-- {
-- sessionState *session = *iter;
-- if(session->mCreateInProgress && (session->mSIPURI == uri))
-- {
-- result = session;
-- break;
-- }
-- }
--
-- return result;
--}
--
--LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participant_id)
--{
-- sessionState *result = NULL;
--
-- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-- {
-- sessionState *session = *iter;
-- if(session->mCallerID == participant_id)
-- {
-- result = session;
-- break;
-- }
-- }
--
-- return result;
--}
--
--LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, const std::string &handle)
--{
-- sessionState *result = NULL;
--
-- if(handle.empty())
-- {
-- // No handle supplied.
-- // Check whether there's already a session with this URI
-- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-- {
-- sessionState *s = *iter;
-- if((s->mSIPURI == uri) || (s->mAlternateSIPURI == uri))
-- {
-- // TODO: I need to think about this logic... it's possible that this case should raise an internal error.
-- result = s;
-- break;
-- }
-- }
-- }
-- else // (!handle.empty())
-- {
-- // Check for an existing session with this handle
-- sessionMap::iterator iter = mSessionsByHandle.find(&handle);
--
-- if(iter != mSessionsByHandle.end())
-- {
-- result = iter->second;
-- }
-- }
--
-- if(!result)
-- {
-- // No existing session found.
--
-- LL_DEBUGS("Voice") << "adding new session: handle " << handle << " URI " << uri << LL_ENDL;
-- result = new sessionState();
-- result->mSIPURI = uri;
-- result->mHandle = handle;
--
-- mSessions.insert(result);
--
-- if(!result->mHandle.empty())
-- {
-- mSessionsByHandle.insert(sessionMap::value_type(&(result->mHandle), result));
-- }
-- }
-- else
-- {
-- // Found an existing session
--
-- if(uri != result->mSIPURI)
-- {
-- // TODO: Should this be an internal error?
-- LL_DEBUGS("Voice") << "changing uri from " << result->mSIPURI << " to " << uri << LL_ENDL;
-- setSessionURI(result, uri);
-- }
--
-- if(handle != result->mHandle)
-- {
-- // TODO: Should this be an internal error?
-- LL_DEBUGS("Voice") << "changing handle from " << result->mHandle << " to " << handle << LL_ENDL;
-- setSessionHandle(result, handle);
-- }
--
-- LL_DEBUGS("Voice") << "returning existing session: handle " << handle << " URI " << uri << LL_ENDL;
-- }
--
-- verifySessionState();
--
-- return result;
--}
--
--void LLVoiceClient::setSessionHandle(sessionState *session, const std::string &handle)
--{
-- // Have to remove the session from the handle-indexed map before changing the handle, or things will break badly.
--
-- if(!session->mHandle.empty())
-- {
-- // Remove session from the map if it should have been there.
-- sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
-- if(iter != mSessionsByHandle.end())
-- {
-- if(iter->second != session)
-- {
-- LL_ERRS("Voice") << "Internal error: session mismatch!" << LL_ENDL;
-- }
--
-- mSessionsByHandle.erase(iter);
-- }
-- else
-- {
-- LL_ERRS("Voice") << "Internal error: session handle not found in map!" << LL_ENDL;
-- }
-- }
--
-- session->mHandle = handle;
--
-- if(!handle.empty())
-- {
-- mSessionsByHandle.insert(sessionMap::value_type(&(session->mHandle), session));
-- }
--
-- verifySessionState();
--}
--
--void LLVoiceClient::setSessionURI(sessionState *session, const std::string &uri)
--{
-- // There used to be a map of session URIs to sessions, which made this complex....
-- session->mSIPURI = uri;
--
-- verifySessionState();
--}
--
--void LLVoiceClient::deleteSession(sessionState *session)
--{
-- // Remove the session from the handle map
-- if(!session->mHandle.empty())
-- {
-- sessionMap::iterator iter = mSessionsByHandle.find(&(session->mHandle));
-- if(iter != mSessionsByHandle.end())
-- {
-- if(iter->second != session)
-- {
-- LL_ERRS("Voice") << "Internal error: session mismatch" << LL_ENDL
-- }
-- mSessionsByHandle.erase(iter);
-- }
-- }
--
-- // Remove the session from the URI map
-- mSessions.erase(session);
--
-- // At this point, the session should be unhooked from all lists and all state should be consistent.
-- verifySessionState();
--
-- // If this is the current audio session, clean up the pointer which will soon be dangling.
-- if(mAudioSession == session)
-- {
-- mAudioSession = NULL;
-- mAudioSessionChanged = true;
-- }
--
-- // ditto for the next audio session
-- if(mNextAudioSession == session)
-- {
-- mNextAudioSession = NULL;
-- }
--
-- // delete the session
-- delete session;
--}
--
--void LLVoiceClient::deleteAllSessions()
--{
-- LL_DEBUGS("Voice") << "called" << LL_ENDL;
--
-- while(!mSessions.empty())
-- {
-- deleteSession(*(sessionsBegin()));
-- }
--
-- if(!mSessionsByHandle.empty())
-- {
-- LL_ERRS("Voice") << "Internal error: empty session map, non-empty handle map" << LL_ENDL
-- }
--}
--
--void LLVoiceClient::verifySessionState(void)
--{
-- // This is mostly intended for debugging problems with session state management.
-- LL_DEBUGS("Voice") << "Total session count: " << mSessions.size() << " , session handle map size: " << mSessionsByHandle.size() << LL_ENDL;
--
-- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-- {
-- sessionState *session = *iter;
--
-- LL_DEBUGS("Voice") << "session " << session << ": handle " << session->mHandle << ", URI " << session->mSIPURI << LL_ENDL;
--
-- if(!session->mHandle.empty())
-- {
-- // every session with a non-empty handle needs to be in the handle map
-- sessionMap::iterator i2 = mSessionsByHandle.find(&(session->mHandle));
-- if(i2 == mSessionsByHandle.end())
-- {
-- LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " not found in session map)" << LL_ENDL;
-- }
-- else
-- {
-- if(i2->second != session)
-- {
-- LL_ERRS("Voice") << "internal error (handle " << session->mHandle << " in session map points to another session)" << LL_ENDL;
-- }
-- }
-- }
-- }
--
-- // check that every entry in the handle map points to a valid session in the session set
-- for(sessionMap::iterator iter = mSessionsByHandle.begin(); iter != mSessionsByHandle.end(); iter++)
-- {
-- sessionState *session = iter->second;
-- sessionIterator i2 = mSessions.find(session);
-- if(i2 == mSessions.end())
-- {
-- LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " not found in session map)" << LL_ENDL;
-- }
-- else
-- {
-- if(session->mHandle != (*i2)->mHandle)
-- {
-- LL_ERRS("Voice") << "internal error (session for handle " << session->mHandle << " points to session with different handle " << (*i2)->mHandle << ")" << LL_ENDL;
-- }
-- }
-- }
--}
--
--LLVoiceClient::buddyListEntry::buddyListEntry(const std::string &uri) :
-- mURI(uri)
--{
-- mOnlineSL = false;
-- mOnlineSLim = false;
-- mCanSeeMeOnline = true;
-- mHasBlockListEntry = false;
-- mHasAutoAcceptListEntry = false;
-- mNameResolved = false;
-- mInVivoxBuddies = false;
-- mInSLFriends = false;
-- mNeedsNameUpdate = false;
--}
--
--void LLVoiceClient::processBuddyListEntry(const std::string &uri, const std::string &displayName)
--{
-- buddyListEntry *buddy = addBuddy(uri, displayName);
-- buddy->mInVivoxBuddies = true;
--}
--
--LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri)
--{
-- std::string empty;
-- buddyListEntry *buddy = addBuddy(uri, empty);
-- if(buddy->mDisplayName.empty())
-- {
-- buddy->mNameResolved = false;
-- }
-- return buddy;
--}
--
--LLVoiceClient::buddyListEntry *LLVoiceClient::addBuddy(const std::string &uri, const std::string &displayName)
--{
-- buddyListEntry *result = NULL;
-- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
--
-- if(iter != mBuddyListMap.end())
-- {
-- // Found a matching buddy already in the map.
-- LL_DEBUGS("Voice") << "adding existing buddy " << uri << LL_ENDL;
-- result = iter->second;
-- }
--
-- if(!result)
-- {
-- // participant isn't already in one list or the other.
-- LL_DEBUGS("Voice") << "adding new buddy " << uri << LL_ENDL;
-- result = new buddyListEntry(uri);
-- result->mDisplayName = displayName;
--
-- if(IDFromName(uri, result->mUUID))
-- {
-- // Extracted UUID from name successfully.
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "Couldn't find ID for buddy " << uri << " (\"" << displayName << "\")" << LL_ENDL;
-- }
--
-- mBuddyListMap.insert(buddyListMap::value_type(&(result->mURI), result));
-- }
--
-- return result;
--}
--
--LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const std::string &uri)
--{
-- buddyListEntry *result = NULL;
-- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
-- if(iter != mBuddyListMap.end())
-- {
-- result = iter->second;
-- }
--
-- return result;
--}
--
--LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddy(const LLUUID &id)
--{
-- buddyListEntry *result = NULL;
-- buddyListMap::iterator iter;
--
-- for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
-+ participantState *participant = findParticipantByID(id);
-+ if(participant)
- {
-- if(iter->second->mUUID == id)
-- {
-- result = iter->second;
-- break;
-- }
-+ result = participant->mServiceType;
- }
-
- return result;
- }
-
--LLVoiceClient::buddyListEntry *LLVoiceClient::findBuddyByDisplayName(const std::string &name)
-+std::string LLVoiceClient::getGroupID(const LLUUID& id)
- {
-- buddyListEntry *result = NULL;
-- buddyListMap::iterator iter;
-+ std::string result;
-
-- for(iter = mBuddyListMap.begin(); iter != mBuddyListMap.end(); iter++)
-+ participantState *participant = findParticipantByID(id);
-+ if(participant)
- {
-- if(iter->second->mDisplayName == name)
-- {
-- result = iter->second;
-- break;
-- }
-+ result = participant->mGroupID;
- }
-
- return result;
- }
-
--void LLVoiceClient::deleteBuddy(const std::string &uri)
--{
-- buddyListMap::iterator iter = mBuddyListMap.find(&uri);
-- if(iter != mBuddyListMap.end())
-- {
-- LL_DEBUGS("Voice") << "deleting buddy " << uri << LL_ENDL;
-- buddyListEntry *buddy = iter->second;
-- mBuddyListMap.erase(iter);
-- delete buddy;
-- }
-- else
-- {
-- LL_DEBUGS("Voice") << "attempt to delete nonexistent buddy " << uri << LL_ENDL;
-- }
--
--}
--
--void LLVoiceClient::deleteAllBuddies(void)
--{
-- while(!mBuddyListMap.empty())
-- {
-- deleteBuddy(*(mBuddyListMap.begin()->first));
-- }
--
-- // Don't want to correlate with friends list when we've emptied the buddy list.
-- mBuddyListMapPopulated = false;
--
-- // Don't want to correlate with friends list when we've reset the block rules.
-- mBlockRulesListReceived = false;
-- mAutoAcceptRulesListReceived = false;
--}
--
--void LLVoiceClient::deleteAllBlockRules(void)
--{
-- // Clear the block list entry flags from all local buddy list entries
-- buddyListMap::iterator buddy_it;
-- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
-- {
-- buddy_it->second->mHasBlockListEntry = false;
-- }
--}
--
--void LLVoiceClient::deleteAllAutoAcceptRules(void)
--{
-- // Clear the auto-accept list entry flags from all local buddy list entries
-- buddyListMap::iterator buddy_it;
-- for(buddy_it = mBuddyListMap.begin(); buddy_it != mBuddyListMap.end(); buddy_it++)
-- {
-- buddy_it->second->mHasAutoAcceptListEntry = false;
-- }
--}
--
--void LLVoiceClient::addBlockRule(const std::string &blockMask, const std::string &presenceOnly)
--{
-- buddyListEntry *buddy = NULL;
--
-- // blockMask is the SIP URI of a friends list entry
-- buddyListMap::iterator iter = mBuddyListMap.find(&blockMask);
-- if(iter != mBuddyListMap.end())
-- {
-- LL_DEBUGS("Voice") << "block list entry for " << blockMask << LL_ENDL;
-- buddy = iter->second;
-- }
--
-- if(buddy == NULL)
-- {
-- LL_DEBUGS("Voice") << "block list entry for unknown buddy " << blockMask << LL_ENDL;
-- buddy = addBuddy(blockMask);
-- }
--
-- if(buddy != NULL)
-- {
-- buddy->mHasBlockListEntry = true;
-- }
--}
--
--void LLVoiceClient::addAutoAcceptRule(const std::string &autoAcceptMask, const std::string &autoAddAsBuddy)
--{
-- buddyListEntry *buddy = NULL;
--
-- // blockMask is the SIP URI of a friends list entry
-- buddyListMap::iterator iter = mBuddyListMap.find(&autoAcceptMask);
-- if(iter != mBuddyListMap.end())
-- {
-- LL_DEBUGS("Voice") << "auto-accept list entry for " << autoAcceptMask << LL_ENDL;
-- buddy = iter->second;
-- }
--
-- if(buddy == NULL)
-- {
-- LL_DEBUGS("Voice") << "auto-accept list entry for unknown buddy " << autoAcceptMask << LL_ENDL;
-- buddy = addBuddy(autoAcceptMask);
-- }
--
-- if(buddy != NULL)
-- {
-- buddy->mHasAutoAcceptListEntry = true;
-- }
--}
--
--void LLVoiceClient::accountListBlockRulesResponse(int statusCode, const std::string &statusString)
--{
-- // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done.
-- mBlockRulesListReceived = true;
--}
--
--void LLVoiceClient::accountListAutoAcceptRulesResponse(int statusCode, const std::string &statusString)
-+BOOL LLVoiceClient::getAreaVoiceDisabled()
- {
-- // Block list entries were updated via addBlockRule() during parsing. Just flag that we're done.
-- mAutoAcceptRulesListReceived = true;
-+ return mAreaVoiceDisabled;
- }
-
- void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
- {
-- mParticipantObservers.insert(observer);
-+ mObservers.insert(observer);
- }
-
- void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
- {
-- mParticipantObservers.erase(observer);
-+ mObservers.erase(observer);
- }
-
--void LLVoiceClient::notifyParticipantObservers()
-+void LLVoiceClient::notifyObservers()
- {
-- for (observer_set_t::iterator it = mParticipantObservers.begin();
-- it != mParticipantObservers.end();
-+ for (observer_set_t::iterator it = mObservers.begin();
-+ it != mObservers.end();
- )
- {
- LLVoiceClientParticipantObserver* observer = *it;
- observer->onChange();
- // In case onChange() deleted an entry.
-- it = mParticipantObservers.upper_bound(observer);
-+ it = mObservers.upper_bound(observer);
- }
- }
-
--void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)
-+void LLVoiceClient::addStatusObserver(LLVoiceClientStatusObserver* observer)
- {
- mStatusObservers.insert(observer);
- }
-
--void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)
-+void LLVoiceClient::removeStatusObserver(LLVoiceClientStatusObserver* observer)
- {
- mStatusObservers.erase(observer);
- }
-
- void LLVoiceClient::notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status)
- {
-- if(mAudioSession)
-+ if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
- {
-- if(status == LLVoiceClientStatusObserver::ERROR_UNKNOWN)
-- {
-- switch(mAudioSession->mErrorStatusCode)
-- {
-- case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
-- case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
-- case 20715:
-- //invalid channel, we may be using a set of poorly cached
-- //info
-- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-- break;
-- case 1009:
-- //invalid username and password
-- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-- break;
-- }
--
-- // Reset the error code to make sure it won't be reused later by accident.
-- mAudioSession->mErrorStatusCode = 0;
-- }
-- else if(status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL)
-+ switch(mVivoxErrorStatusCode)
- {
-- switch(mAudioSession->mErrorStatusCode)
-- {
-- case 404: // NOT_FOUND
-- case 480: // TEMPORARILY_UNAVAILABLE
-- case 408: // REQUEST_TIMEOUT
-- // call failed because other user was not available
-- // treat this as an error case
-- status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
--
-- // Reset the error code to make sure it won't be reused later by accident.
-- mAudioSession->mErrorStatusCode = 0;
-- break;
-- }
-+ case 20713: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_FULL; break;
-+ case 20714: status = LLVoiceClientStatusObserver::ERROR_CHANNEL_LOCKED; break;
-+ case 20715:
-+ //invalid channel, we may be using a set of poorly cached
-+ //info
-+ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-+ break;
-+ case 1009:
-+ //invalid username and password
-+ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-+ break;
- }
-+
-+ // Reset the error code to make sure it won't be reused later by accident.
-+ mVivoxErrorStatusCode = 0;
- }
--
-- LL_DEBUGS("Voice")
-- << " " << LLVoiceClientStatusObserver::status2string(status)
-- << ", session URI " << getAudioSessionURI()
-- << (inSpatialChannel()?", proximal is true":", proximal is false")
-- << LL_ENDL;
-+
-+ if (status == LLVoiceClientStatusObserver::STATUS_LEFT_CHANNEL
-+ //NOT_FOUND || TEMPORARILY_UNAVAILABLE || REQUEST_TIMEOUT
-+ && (mVivoxErrorStatusCode == 404 || mVivoxErrorStatusCode == 480 || mVivoxErrorStatusCode == 408))
-+ {
-+ // call failed because other user was not available
-+ // treat this as an error case
-+ status = LLVoiceClientStatusObserver::ERROR_NOT_AVAILABLE;
-+
-+ // Reset the error code to make sure it won't be reused later by accident.
-+ mVivoxErrorStatusCode = 0;
-+ }
-+
-+ LL_DEBUGS("Voice") << " " << LLVoiceClientStatusObserver::status2string(status) << ", session URI " << mSessionURI << LL_ENDL;
-
- for (status_observer_set_t::iterator it = mStatusObservers.begin();
- it != mStatusObservers.end();
- )
- {
- LLVoiceClientStatusObserver* observer = *it;
-- observer->onChange(status, getAudioSessionURI(), inSpatialChannel());
-+ observer->onChange(status, mSessionURI, !mNonSpatialChannel);
- // In case onError() deleted an entry.
- it = mStatusObservers.upper_bound(observer);
- }
-
- }
-
--void LLVoiceClient::addObserver(LLFriendObserver* observer)
--{
-- mFriendObservers.insert(observer);
--}
--
--void LLVoiceClient::removeObserver(LLFriendObserver* observer)
--{
-- mFriendObservers.erase(observer);
--}
--
--void LLVoiceClient::notifyFriendObservers()
--{
-- for (friend_observer_set_t::iterator it = mFriendObservers.begin();
-- it != mFriendObservers.end();
-- )
-- {
-- LLFriendObserver* observer = *it;
-- it++;
-- // The only friend-related thing we notify on is online/offline transitions.
-- observer->changed(LLFriendObserver::ONLINE);
-- }
--}
--
--void LLVoiceClient::lookupName(const LLUUID &id)
--{
-- gCacheName->getName(id, onAvatarNameLookup);
--}
--
- //static
--void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
--{
-- if(gVoiceClient)
-- {
-- std::string name = llformat("%s %s", first.c_str(), last.c_str());
-- gVoiceClient->avatarNameResolved(id, name);
-- }
--}
-+// void LLVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data)
-+// {
-+// participantState* statep = gVoiceClient->findParticipantByID(id);
-
--void LLVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
--{
-- // If the avatar whose name just resolved is on our friends list, resync the friends list.
-- if(LLAvatarTracker::instance().getBuddyInfo(id) != NULL)
-- {
-- mFriendsListDirty = true;
-- }
-+// if (statep)
-+// {
-+// statep->mDisplayName = first + " " + last;
-+// }
-
-- // Iterate over all sessions.
-- for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
-- {
-- sessionState *session = *iter;
--
-- // Check for this user as a participant in this session
-- participantState *participant = session->findParticipantByID(id);
-- if(participant)
-- {
-- // Found -- fill in the name
-- participant->mAccountName = name;
-- // and post a "participants updated" message to listeners later.
-- session->mParticipantsChanged = true;
-- }
--
-- // Check whether this is a p2p session whose caller name just resolved
-- if(session->mCallerID == id)
-- {
-- // this session's "caller ID" just resolved. Fill in the name.
-- session->mName = name;
-- if(session->mTextInvitePending)
-- {
-- session->mTextInvitePending = false;
--
-- // We don't need to call gIMMgr->addP2PSession() here. The first incoming message will create the panel.
-- }
-- if(session->mVoiceInvitePending)
-- {
-- session->mVoiceInvitePending = false;
--
-- gIMMgr->inviteToSession(
-- session->mIMSessionID,
-- session->mName,
-- session->mCallerID,
-- session->mName,
-- IM_SESSION_P2P_INVITE,
-- LLIMMgr::INVITATION_TYPE_VOICE,
-- session->mHandle,
-- session->mSIPURI);
-- }
--
-- }
-- }
--}
-+// gVoiceClient->notifyObservers();
-+// }
-
- class LLViewerParcelVoiceInfo : public LLHTTPNode
- {
-diff --git a/linden/indra/newview/llvoiceclient.h b/linden/indra/newview/llvoiceclient.h
-index 13dd974..d0b7839 100644
---- a/linden/indra/newview/llvoiceclient.h
-+++ b/linden/indra/newview/llvoiceclient.h
-@@ -41,7 +41,6 @@ class LLVivoxProtocolParser;
- #include "v3math.h"
- #include "llframetimer.h"
- #include "llviewerregion.h"
--#include "llcallingcard.h" // for LLFriendObserver
-
- class LLVoiceClientParticipantObserver
- {
-@@ -92,10 +91,41 @@ class LLVoiceClient: public LLSingleton
-
- public:
-
-+ enum serviceType
-+ {
-+ serviceTypeUnknown, // Unknown, returned if no data on the avatar is available
-+ serviceTypeA, // spatialized local chat
-+ serviceTypeB, // remote multi-party chat
-+ serviceTypeC // one-to-one and small group chat
-+ };
- static F32 OVERDRIVEN_POWER_LEVEL;
-
- void updateSettings(); // call after loading settings and whenever they change
-
-+ /////////////////////////////
-+ // session control messages
-+ void connect();
-+
-+ void connectorCreate();
-+ void connectorShutdown();
-+
-+ void requestVoiceAccountProvision(S32 retries = 3);
-+ void userAuthorized(
-+ const std::string& firstName,
-+ const std::string& lastName,
-+ const LLUUID &agentID);
-+ void login(const std::string& accountName, const std::string &password);
-+ void loginSendMessage();
-+ void logout();
-+ void logoutSendMessage();
-+
-+ void channelGetListSendMessage();
-+ void sessionCreateSendMessage();
-+ void sessionConnectSendMessage();
-+ void sessionTerminate();
-+ void sessionTerminateSendMessage();
-+ void sessionTerminateByHandle(std::string &sessionHandle);
-+
- void getCaptureDevicesSendMessage();
- void getRenderDevicesSendMessage();
-
-@@ -140,32 +170,23 @@ class LLVoiceClient: public LLSingleton
-
- /////////////////////////////
- // Response/Event handlers
-- void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
-- void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle, int numberOfAliases);
-- void sessionCreateResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
-- void sessionGroupAddSessionResponse(std::string &requestId, int statusCode, std::string &statusString, std::string &sessionHandle);
-- void sessionConnectResponse(std::string &requestId, int statusCode, std::string &statusString);
-+ void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle);
-+ void loginResponse(int statusCode, std::string &statusString, std::string &accountHandle);
-+ void channelGetListResponse(int statusCode, std::string &statusString);
-+ void sessionCreateResponse(int statusCode, std::string &statusString, std::string &sessionHandle);
-+ void sessionConnectResponse(int statusCode, std::string &statusString);
-+ void sessionTerminateResponse(int statusCode, std::string &statusString);
- void logoutResponse(int statusCode, std::string &statusString);
- void connectorShutdownResponse(int statusCode, std::string &statusString);
-
-- void accountLoginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
-- void mediaStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, int statusCode, std::string &statusString, int state, bool incoming);
-- void textStreamUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, bool enabled, int state, bool incoming);
-- void sessionAddedEvent(std::string &uriString, std::string &alias, std::string &sessionHandle, std::string &sessionGroupHandle, bool isChannel, bool incoming, std::string &nameString, std::string &applicationString);
-- void sessionGroupAddedEvent(std::string &sessionGroupHandle);
-- void sessionRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle);
-- void participantAddedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString, std::string &displayNameString, int participantType);
-- void participantRemovedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, std::string &nameString);
-- void participantUpdatedEvent(std::string &sessionHandle, std::string &sessionGroupHandle, std::string &uriString, std::string &alias, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
-+ void loginStateChangeEvent(std::string &accountHandle, int statusCode, std::string &statusString, int state);
-+ void sessionNewEvent(std::string &accountHandle, std::string &eventSessionHandle, int state, std::string &nameString, std::string &uriString);
-+ void sessionStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, std::string &sessionHandle, int state, bool isChannel, std::string &nameString);
-+ void participantStateChangeEvent(std::string &uriString, int statusCode, std::string &statusString, int state, std::string &nameString, std::string &displayNameString, int participantType);
-+ void participantPropertiesEvent(std::string &uriString, int statusCode, std::string &statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, F32 energy);
- void auxAudioPropertiesEvent(F32 energy);
-- void buddyPresenceEvent(std::string &uriString, std::string &alias, std::string &statusString, std::string &applicationString);
-- void messageEvent(std::string &sessionHandle, std::string &uriString, std::string &alias, std::string &messageHeader, std::string &messageBody, std::string &applicationString);
-- void sessionNotificationEvent(std::string &sessionHandle, std::string &uriString, std::string ¬ificationType);
-- void subscriptionEvent(std::string &buddyURI, std::string &subscriptionHandle, std::string &alias, std::string &displayName, std::string &applicationString, std::string &subscriptionType);
--
-- void buddyListChanged();
-+
- void muteListChanged();
-- void updateFriends(U32 mask);
-
- /////////////////////////////
- // Sending updates of current state
-@@ -189,6 +210,7 @@ static void updatePosition(void);
- void setVoiceVolume(F32 volume);
- void setMicGain(F32 volume);
- void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal)
-+ void setVivoxDebugServerName(std::string &serverName);
- void setLipSyncEnabled(BOOL enabled);
- BOOL lipSyncEnabled();
-
-@@ -203,261 +225,57 @@ static void updatePosition(void);
- BOOL getIsSpeaking(const LLUUID& id);
- BOOL getIsModeratorMuted(const LLUUID& id);
- F32 getCurrentPower(const LLUUID& id); // "power" is related to "amplitude" in a defined way. I'm just not sure what the formula is...
-+ BOOL getPTTPressed(const LLUUID& id); // This is the inverse of the "locally muted" property.
- BOOL getOnMuteList(const LLUUID& id);
- F32 getUserVolume(const LLUUID& id);
- std::string getDisplayName(const LLUUID& id);
-
- // MBW -- XXX -- Not sure how to get this data out of the TVC
- BOOL getUsingPTT(const LLUUID& id);
-+ serviceType getServiceType(const LLUUID& id); // type of chat the user is involved in (see bHear scope doc for definitions of A/B/C)
- std::string getGroupID(const LLUUID& id); // group ID if the user is in group chat (empty string if not applicable)
-
- /////////////////////////////
- BOOL getAreaVoiceDisabled(); // returns true if the area the avatar is in is speech-disabled.
- // Use this to determine whether to show a "no speech" icon in the menu bar.
--
-- /////////////////////////////
-- // Recording controls
-- void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
-- void recordingLoopSave(const std::string& filename);
-- void recordingStop();
--
-- // Playback controls
-- void filePlaybackStart(const std::string& filename);
-- void filePlaybackStop();
-- void filePlaybackSetPaused(bool paused);
-- void filePlaybackSetMode(bool vox = false, float speed = 1.0f);
--
--
-- // This is used by the string-keyed maps below, to avoid storing the string twice.
-- // The 'const std::string *' in the key points to a string actually stored in the object referenced by the map.
-- // The add and delete operations for each map allocate and delete in the right order to avoid dangling references.
-- // The default compare operation would just compare pointers, which is incorrect, so they must use this comparitor instead.
-- struct stringMapComparitor
-- {
-- bool operator()(const std::string* a, const std::string * b) const
-- {
-- return a->compare(*b) < 0;
-- }
-- };
-
-- struct uuidMapComparitor
-- {
-- bool operator()(const LLUUID* a, const LLUUID * b) const
-- {
-- return *a < *b;
-- }
-- };
--
- struct participantState
- {
- public:
- participantState(const std::string &uri);
--
-- bool updateMuteState();
--
- std::string mURI;
-- LLUUID mAvatarID;
-- std::string mAccountName;
-+ std::string mName;
- std::string mDisplayName;
-+ bool mPTT;
-+ bool mIsSpeaking;
-+ bool mIsModeratorMuted;
- LLFrameTimer mSpeakingTimeout;
- F32 mLastSpokeTimestamp;
- F32 mPower;
- int mVolume;
-+ serviceType mServiceType;
- std::string mGroupID;
-- int mUserVolume;
-- bool mPTT;
-- bool mIsSpeaking;
-- bool mIsModeratorMuted;
- bool mOnMuteList; // true if this avatar is on the user's mute list (and should be muted)
-+ int mUserVolume;
- bool mVolumeDirty; // true if this participant needs a volume command sent (either mOnMuteList or mUserVolume has changed)
- bool mAvatarIDValid;
-- bool mIsSelf;
-- };
-- typedef std::map participantMap;
--
-- typedef std::map participantUUIDMap;
--
-- enum streamState
-- {
-- streamStateUnknown = 0,
-- streamStateIdle = 1,
-- streamStateConnected = 2,
-- streamStateRinging = 3,
-+ LLUUID mAvatarID;
- };
-+ typedef std::map participantMap;
-
-- struct sessionState
-- {
-- public:
-- sessionState();
-- ~sessionState();
--
-- participantState *addParticipant(const std::string &uri);
-- // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
-- // Take care not to use the pointer again after that.
-- void removeParticipant(participantState *participant);
-- void removeAllParticipants();
--
-- participantState *findParticipant(const std::string &uri);
-- participantState *findParticipantByID(const LLUUID& id);
--
-- std::string mHandle;
-- std::string mGroupHandle;
-- std::string mSIPURI;
-- std::string mAlias;
-- std::string mName;
-- std::string mAlternateSIPURI;
-- std::string mHash; // Channel password
-- std::string mErrorStatusString;
-- std::queue mTextMsgQueue;
--
-- LLUUID mIMSessionID;
-- LLUUID mCallerID;
-- int mErrorStatusCode;
-- int mMediaStreamState;
-- int mTextStreamState;
-- bool mCreateInProgress; // True if a Session.Create has been sent for this session and no response has been received yet.
-- bool mMediaConnectInProgress; // True if a Session.MediaConnect has been sent for this session and no response has been received yet.
-- bool mVoiceInvitePending; // True if a voice invite is pending for this session (usually waiting on a name lookup)
-- bool mTextInvitePending; // True if a text invite is pending for this session (usually waiting on a name lookup)
-- bool mSynthesizedCallerID; // True if the caller ID is a hash of the SIP URI -- this means we shouldn't do a name lookup.
-- bool mIsChannel; // True for both group and spatial channels (false for p2p, PSTN)
-- bool mIsSpatial; // True for spatial channels
-- bool mIsP2P;
-- bool mIncoming;
-- bool mVoiceEnabled;
-- bool mReconnect; // Whether we should try to reconnect to this session if it's dropped
-- // Set to true when the mute state of someone in the participant list changes.
-- // The code will have to walk the list to find the changed participant(s).
-- bool mVolumeDirty;
--
-- bool mParticipantsChanged;
-- participantMap mParticipantsByURI;
-- participantUUIDMap mParticipantsByUUID;
-- };
--
-+ participantState *findParticipant(const std::string &uri);
-+ participantState *findParticipantByAvatar(LLVOAvatar *avatar);
- participantState *findParticipantByID(const LLUUID& id);
-- participantMap *getParticipantList(void);
--
-- typedef std::map sessionMap;
-- typedef std::set sessionSet;
--
-- typedef sessionSet::iterator sessionIterator;
-- sessionIterator sessionsBegin(void);
-- sessionIterator sessionsEnd(void);
--
-- sessionState *findSession(const std::string &handle);
-- sessionState *findSessionBeingCreatedByURI(const std::string &uri);
-- sessionState *findSession(const LLUUID &participant_id);
-- sessionState *findSessionByCreateID(const std::string &create_id);
--
-- sessionState *addSession(const std::string &uri, const std::string &handle = LLStringUtil::null);
-- void setSessionHandle(sessionState *session, const std::string &handle = LLStringUtil::null);
-- void setSessionURI(sessionState *session, const std::string &uri);
-- void deleteSession(sessionState *session);
-- void deleteAllSessions(void);
--
-- void verifySessionState(void);
--
-- void joinedAudioSession(sessionState *session);
-- void leftAudioSession(sessionState *session);
--
-- // This is called in several places where the session _may_ need to be deleted.
-- // It contains logic for whether to delete the session or keep it around.
-- void reapSession(sessionState *session);
--
-- // Returns true if the session seems to indicate we've moved to a region on a different voice server
-- bool sessionNeedsRelog(sessionState *session);
--
-- struct buddyListEntry
-- {
-- buddyListEntry(const std::string &uri);
-- std::string mURI;
-- std::string mDisplayName;
-- LLUUID mUUID;
-- bool mOnlineSL;
-- bool mOnlineSLim;
-- bool mCanSeeMeOnline;
-- bool mHasBlockListEntry;
-- bool mHasAutoAcceptListEntry;
-- bool mNameResolved;
-- bool mInSLFriends;
-- bool mInVivoxBuddies;
-- bool mNeedsNameUpdate;
-- };
--
-- typedef std::map buddyListMap;
-
-- // This should be called when parsing a buddy list entry sent by SLVoice.
-- void processBuddyListEntry(const std::string &uri, const std::string &displayName);
--
-- buddyListEntry *addBuddy(const std::string &uri);
-- buddyListEntry *addBuddy(const std::string &uri, const std::string &displayName);
-- buddyListEntry *findBuddy(const std::string &uri);
-- buddyListEntry *findBuddy(const LLUUID &id);
-- buddyListEntry *findBuddyByDisplayName(const std::string &name);
-- void deleteBuddy(const std::string &uri);
-- void deleteAllBuddies(void);
--
-- void deleteAllBlockRules(void);
-- void addBlockRule(const std::string &blockMask, const std::string &presenceOnly);
-- 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);
--
-- /////////////////////////////
-- // session control messages
-- void connectorCreate();
-- void connectorShutdown();
--
-- void requestVoiceAccountProvision(S32 retries = 3);
-- void userAuthorized(
-- const std::string& firstName,
-- const std::string& lastName,
-- const LLUUID &agentID);
-- void login(
-- const std::string& account_name,
-- const std::string& password,
-- const std::string& voice_sip_uri_hostname,
-- const std::string& voice_account_server_uri);
-- void loginSendMessage();
-- void logout();
-- void logoutSendMessage();
--
-- void accountListBlockRulesSendMessage();
-- void accountListAutoAcceptRulesSendMessage();
--
-- 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 sessionTerminateSendMessage(sessionState *session);
-- void sessionMediaDisconnectSendMessage(sessionState *session);
-- void sessionTextDisconnectSendMessage(sessionState *session);
-+ participantMap *getParticipantList(void);
-
-- // Pokes the state machine to leave the audio session next time around.
-- void sessionTerminate();
--
-- // Pokes the state machine to shut down the connector and restart it.
-- void requestRelog();
--
-- // Does the actual work to get out of the audio session
-- void leaveAudioSession();
--
- void addObserver(LLVoiceClientParticipantObserver* observer);
- void removeObserver(LLVoiceClientParticipantObserver* observer);
-
-- void addObserver(LLVoiceClientStatusObserver* observer);
-- void removeObserver(LLVoiceClientStatusObserver* observer);
--
-- void addObserver(LLFriendObserver* observer);
-- void removeObserver(LLFriendObserver* observer);
--
-- void lookupName(const LLUUID &id);
-- static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
-- void avatarNameResolved(const LLUUID &id, const std::string &name);
-+ void addStatusObserver(LLVoiceClientStatusObserver* observer);
-+ void removeStatusObserver(LLVoiceClientStatusObserver* observer);
-
-+// static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* user_data);
- typedef std::vector deviceList;
-
- deviceList *getCaptureDevices();
-@@ -469,16 +287,8 @@ static void updatePosition(void);
- void setSpatialChannel(
- const std::string &uri,
- const std::string &credentials);
-- // start a voice session with the specified user
-- void callUser(const LLUUID &uuid);
--
-- // Send a text message to the specified user, initiating the session if necessary.
-- bool sendTextMessage(const LLUUID& participant_id, const std::string& message);
--
-- // close any existing text IM session with the specified user
-- void endUserIMSession(const LLUUID &uuid);
--
-- bool answerInvite(std::string &sessionHandle);
-+ void callUser(LLUUID &uuid);
-+ void answerInvite(std::string &sessionHandle, LLUUID& other_user_id);
- void declineInvite(std::string &sessionHandle);
- void leaveNonSpatialChannel();
-
-@@ -491,37 +301,33 @@ static void updatePosition(void);
- bool inProximalChannel();
-
- std::string sipURIFromID(const LLUUID &id);
--
-- // Returns true if the indicated user is online via SIP presence according to SLVoice.
-- // Note that we only get SIP presence data for other users that are in our vivox buddy list.
-- bool isOnlineSIP(const LLUUID &id);
--
-+
- private:
-
- // internal state for a simple state machine. This is used to deal with the asynchronous nature of some of the messages.
- // Note: if you change this list, please make corresponding changes to LLVoiceClient::state2string().
- enum state
- {
-- stateDisableCleanup,
- stateDisabled, // Voice is turned off.
- stateStart, // Class is initialized, socket is created
- stateDaemonLaunched, // Daemon has been launched
- stateConnecting, // connect() call has been issued
-- stateConnected, // connection to the daemon has been made, send some initial setup commands.
- stateIdle, // socket is connected, ready for messaging
-- stateMicTuningStart,
-- stateMicTuningRunning,
-- stateMicTuningStop,
- stateConnectorStart, // connector needs to be started
- stateConnectorStarting, // waiting for connector handle
- stateConnectorStarted, // connector handle received
-+ stateMicTuningNoLogin, // mic tuning before login
- stateLoginRetry, // need to retry login (failed due to changing password)
- stateLoginRetryWait, // waiting for retry timer
- stateNeedsLogin, // send login request
- stateLoggingIn, // waiting for account handle
- stateLoggedIn, // account handle received
-- stateCreatingSessionGroup, // Creating the main session group
- stateNoChannel, //
-+ stateMicTuningStart,
-+ stateMicTuningRunning,
-+ stateMicTuningStop,
-+ stateSessionCreate, // need to send Session.Create command
-+ stateSessionConnect, // need to send Session.Connect command
- stateJoiningSession, // waiting for session handle
- stateSessionJoined, // session handle received
- stateRunning, // in session, steady state
-@@ -548,7 +354,7 @@ static void updatePosition(void);
-
- state mState;
- bool mSessionTerminateRequested;
-- bool mRelogRequested;
-+ bool mNonSpatialChannel;
-
- void setState(state inState);
- state getState(void) { return mState; };
-@@ -571,7 +377,18 @@ static void updatePosition(void);
- std::string mAccountDisplayName;
- std::string mAccountFirstName;
- std::string mAccountLastName;
--
-+
-+ std::string mNextP2PSessionURI; // URI of the P2P session to join next
-+ std::string mNextSessionURI; // URI of the session to join next
-+ std::string mNextSessionHandle; // Session handle of the session to join next
-+ std::string mNextSessionHash; // Password hash for the session to join next
-+ bool mNextSessionSpatial; // Will next session be a spatial chat?
-+ bool mNextSessionNoReconnect; // Next session should not auto-reconnect (i.e. user -> user chat)
-+ bool mNextSessionResetOnClose; // If this is true, go back to spatial chat when the next session terminates.
-+
-+ std::string mSessionStateEventHandle; // session handle received in SessionStateChangeEvents
-+ std::string mSessionStateEventURI; // session URI received in SessionStateChangeEvents
-+
- bool mTuningMode;
- float mTuningEnergy;
- std::string mTuningAudioFile;
-@@ -582,40 +399,32 @@ static void updatePosition(void);
- state mTuningExitState; // state to return to when we leave tuning mode.
-
- std::string mSpatialSessionURI;
-- std::string mSpatialSessionCredentials;
--
-- std::string mMainSessionGroupHandle; // handle of the "main" session group.
-+
-+ bool mSessionResetOnClose;
-+
-+ int mVivoxErrorStatusCode;
-+ std::string mVivoxErrorStatusString;
-
- std::string mChannelName; // Name of the channel to be looked up
- bool mAreaVoiceDisabled;
-- sessionState *mAudioSession; // Session state for the current audio session
-- bool mAudioSessionChanged; // set to true when the above pointer gets changed, so observers can be notified.
--
-- sessionState *mNextAudioSession; // Session state for the audio session we're trying to join
--
--// std::string mSessionURI; // URI of the session we're in.
--// std::string mSessionHandle; // returned by ?
-+ std::string mSessionURI; // URI of the session we're in.
-+ bool mSessionP2P; // true if this session is a p2p call
-
- S32 mCurrentParcelLocalID; // Used to detect parcel boundary crossings
- std::string mCurrentRegionName; // Used to detect parcel boundary crossings
-
- std::string mConnectorHandle; // returned by "Create Connector" message
- std::string mAccountHandle; // returned by login message
-- int mNumberOfAliases;
-+ std::string mSessionHandle; // returned by ?
- U32 mCommandCookie;
-
-- std::string mVoiceAccountServerURI;
-- std::string mVoiceSIPURIHostName;
-+ std::string mAccountServerName;
-+ std::string mAccountServerURI;
-
- int mLoginRetryCount;
-
-- sessionMap mSessionsByHandle; // Active sessions, indexed by session handle. Sessions which are being initiated may not be in this map.
-- sessionSet mSessions; // All sessions, not indexed. This is the canonical session list.
--
-- bool mBuddyListMapPopulated;
-- bool mBlockRulesListReceived;
-- bool mAutoAcceptRulesListReceived;
-- buddyListMap mBuddyListMap;
-+ participantMap mParticipantMap;
-+ bool mParticipantMapChanged;
-
- deviceList mCaptureDevices;
- deviceList mRenderDevices;
-@@ -625,41 +434,40 @@ static void updatePosition(void);
- bool mCaptureDeviceDirty;
- bool mRenderDeviceDirty;
-
-+ participantState *addParticipant(const std::string &uri);
-+ // Note: after removeParticipant returns, the participant* that was passed to it will have been deleted.
-+ // Take care not to use the pointer again after that.
-+ void removeParticipant(participantState *participant);
-+ void removeAllParticipants();
-+
-+ void updateMuteState(participantState *participant);
-+
-+ typedef std::map channelMap;
-+ channelMap mChannelMap;
-+
-+ // These are used by the parser when processing a channel list response.
-+ void clearChannelMap(void);
-+ void addChannelMapEntry(std::string &name, std::string &uri);
-+ std::string findChannelURI(std::string &name);
-+
- // 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 joinSession(sessionState *session);
-+ void switchChannel(std::string uri = std::string(), bool spatial = true, bool noReconnect = false, std::string hash = "");
-+ void joinSession(std::string handle, std::string uri);
-
--static std::string nameFromAvatar(LLVOAvatar *avatar);
--static std::string nameFromID(const LLUUID &id);
--static bool IDFromName(const std::string name, LLUUID &uuid);
--static std::string displayNameFromAvatar(LLVOAvatar *avatar);
-+ std::string nameFromAvatar(LLVOAvatar *avatar);
-+ std::string nameFromID(const LLUUID &id);
-+ bool IDFromName(const std::string name, LLUUID &uuid);
-+ std::string displayNameFromAvatar(LLVOAvatar *avatar);
- std::string sipURIFromAvatar(LLVOAvatar *avatar);
- std::string sipURIFromName(std::string &name);
--
-- // Returns the name portion of the SIP URI if the string looks vaguely like a SIP URI, or an empty string if not.
--static std::string nameFromsipURI(const std::string &uri);
--
-- bool inSpatialChannel(void);
-- std::string getAudioSessionURI();
-- std::string getAudioSessionHandle();
-
- void sendPositionalUpdate(void);
-
- void buildSetCaptureDevice(std::ostringstream &stream);
- void buildSetRenderDevice(std::ostringstream &stream);
-- void buildLocalAudioUpdates(std::ostringstream &stream);
--
-- void clearAllLists();
-- void checkFriend(const LLUUID& id);
-- void sendFriendsListUpdates();
--
-- // start a text IM session with the specified user
-- // This will be asynchronous, the session may be established at a future time.
-- sessionState* startUserIMSession(const LLUUID& uuid);
-- void sendQueuedTextMessages(sessionState *session);
-
- void enforceTether(void);
-
-@@ -683,9 +491,10 @@ static std::string nameFromsipURI(const std::string &uri);
- bool mPTTIsToggle;
- bool mUserPTTState;
- bool mMuteMic;
--
-- // Set to true when the friends list is known to have changed.
-- bool mFriendsListDirty;
-+
-+ // Set to true when the mute state of someone in the participant list changes.
-+ // The code will have to walk the list to find the changed participant(s).
-+ bool mVolumeDirty;
-
- enum
- {
-@@ -713,18 +522,14 @@ static std::string nameFromsipURI(const std::string &uri);
- BOOL mLipSyncEnabled;
-
- typedef std::set observer_set_t;
-- observer_set_t mParticipantObservers;
-+ observer_set_t mObservers;
-
-- void notifyParticipantObservers();
-+ void notifyObservers();
-
- typedef std::set status_observer_set_t;
- status_observer_set_t mStatusObservers;
-
- void notifyStatusObservers(LLVoiceClientStatusObserver::EStatusType status);
--
-- typedef std::set friend_observer_set_t;
-- friend_observer_set_t mFriendObservers;
-- void notifyFriendObservers();
- };
-
- extern LLVoiceClient *gVoiceClient;
diff --git a/stack_trace.log b/stack_trace.log
deleted file mode 100644
index b04e344..0000000
--- a/stack_trace.log
+++ /dev/null
@@ -1,32 +0,0 @@
-0: ELF(do_elfio_glibc_backtrace()+0x424) [0x9962c13]
-1: ELF(LLAppViewerLinux::handleSyncCrashTrace()+0xb) [0x9963533]
-2: ELF(LLAppViewer::handleSyncViewerCrash()+0x20) [0x85181a2]
-3: ELF(LLApp::runSyncErrorHandler()+0x16) [0x9e7d384]
-4: ELF(LLApp::setError()+0x17) [0x9e7d40d]
-5: ELF(default_unix_signal_handler(int, siginfo*, void*)+0xd22) [0x9e7f08e]
-6: [0xb807640c]
-7: /usr/lib/libstdc++.so.6(_ZNSs6assignERKSs+0x2b) [0xb617825b]
-8: /usr/lib/libstdc++.so.6(_ZNSsaSERKSs+0x24) [0xb6178334]
-9: ELF(attach_label(std::string&, void*)+0x32) [0x9563d7b]
-10: ELF(LLMenuItemCallGL::buildDrawLabel()+0x232) [0x9c2d012]
-11: ELF(LLMenuGL::arrange()+0xb07) [0x9c31719]
-12: ELF(LLMenuGL::append(LLMenuItemGL*)+0x4c) [0x9c280ca]
-13: ELF(LLMenuGL::arrange()+0x6b3) [0x9c312c5]
-14: ELF(LLMenuGL::append(LLMenuItemGL*)+0x4c) [0x9c280ca]
-15: ELF(LLVOAvatar::buildCharacter()+0x3a8e) [0x974689c]
-16: ELF(LLVOAvatar::LLVOAvatar(LLUUID const&, unsigned char, LLViewerRegion*)+0x4140) [0x97566e4]
-17: ELF(LLViewerObject::createObject(LLUUID const&, unsigned char, LLViewerRegion*)+0x193) [0x960ab0d]
-18: ELF(LLViewerObjectList::createObject(unsigned char, LLViewerRegion*, LLUUID const&, unsigned int, LLHost const&)+0x8f) [0x961c9f3]
-19: ELF(LLViewerObjectList::processObjectUpdate(LLMessageSystem*, void**, e_object_update_type, bool, bool)+0x8d1) [0x961e83d]
-20: ELF(process_object_update(LLMessageSystem*, void**)+0x9d) [0x95ccc9e]
-21: ELF(LLMessageTemplate::callHandlerFunc(LLMessageSystem*) const+0x47) [0x9af995d]
-22: ELF(LLTemplateMessageReader::decodeData(unsigned char const*, LLHost const&)+0xcc8) [0x9b2d12c]
-23: ELF(LLTemplateMessageReader::readMessage(unsigned char const*, LLHost const&)+0x1f) [0x9b2d653]
-24: ELF(LLMessageSystem::checkMessages(long long)+0x1211) [0x9af0205]
-25: ELF(LLMessageSystem::checkAllMessages(long long, LLPumpIO*)+0x2b) [0x9af057d]
-26: ELF(LLAppViewer::idleNetwork()+0x2ab) [0x8519b85]
-27: ELF(LLAppViewer::idle()+0xd5c) [0x85355fe]
-28: ELF(LLAppViewer::mainLoop()+0x7fe) [0x8536cdc]
-29: ELF(main+0x213) [0x996433c]
-30: /lib/i686/cmov/libc.so.6(__libc_start_main+0xe5) [0xb5f45775]
-31: bin/do-not-directly-run-imprudence-bin [0x846f7e1]
--
cgit v1.1
From 29a0f7cfdd33e8d18ad5d932eefa67332d5b5ed3 Mon Sep 17 00:00:00 2001
From: Armin Weatherwax
Date: Thu, 9 Jul 2009 17:50:25 +0200
Subject: looks like working now
modified: linden/indra/newview/llchatbar.cpp
modified: linden/indra/newview/llviewerwindow.cpp
modified: linden/indra/newview/llvoavatar.cpp
---
linden/indra/newview/llchatbar.cpp | 1 +
linden/indra/newview/llviewerwindow.cpp | 88 ++++++++++++++++++---------------
linden/indra/newview/llvoavatar.cpp | 13 ++++-
3 files changed, 61 insertions(+), 41 deletions(-)
diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp
index 59aa572..02a62b6 100644
--- a/linden/indra/newview/llchatbar.cpp
+++ b/linden/indra/newview/llchatbar.cpp
@@ -115,6 +115,7 @@ LLChatBar::LLChatBar()
LLChatBar::~LLChatBar()
{
+ gGestureManager.removeObserver(mObserver);
delete mObserver;
mObserver = NULL;
// LLView destructor cleans up children
diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp
index 7e6c24f..1554075 100644
--- a/linden/indra/newview/llviewerwindow.cpp
+++ b/linden/indra/newview/llviewerwindow.cpp
@@ -1829,69 +1829,82 @@ void LLViewerWindow::initWorldUI()
S32 width = mRootView->getRect().getWidth();
LLRect full_window(0, height, width, 0);
- if ( gBottomPanel == NULL ) // Don't re-enter if objects are alreay created
- {
- // panel containing chatbar, toolbar, and overlay, over floaters
- gBottomPanel = new LLBottomPanel(mRootView->getRect());
- mRootView->addChild(gBottomPanel);
+ if (gBottomPanel)
+ mRootView->removeChild(gBottomPanel, TRUE);
+ // panel containing chatbar, toolbar, and overlay, over floaters
+ gBottomPanel = new LLBottomPanel(mRootView->getRect());
+ mRootView->addChild(gBottomPanel);
- // View for hover information
- gHoverView = new LLHoverView(std::string("gHoverView"), full_window);
- gHoverView->setVisible(TRUE);
- mRootView->addChild(gHoverView);
+ if (gHoverView)
+ mRootView->removeChild(gHoverView, TRUE);
+ // View for hover information
+ gHoverView = new LLHoverView(std::string("gHoverView"), full_window);
+ gHoverView->setVisible(TRUE);
+ mRootView->addChild(gHoverView);
- gIMMgr = LLIMMgr::getInstance();
+ gIMMgr = LLIMMgr::getInstance();
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
- {
- LLFloaterChat::getInstance(LLSD())->loadHistory();
- }
+ if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+ {
+ LLFloaterChat::getInstance(LLSD())->loadHistory();
+ }
- LLRect morph_view_rect = full_window;
- morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
- morph_view_rect.mTop = full_window.mTop - 32;
- gMorphView = new LLMorphView(std::string("gMorphView"), morph_view_rect );
- mRootView->addChild(gMorphView);
- gMorphView->setVisible(FALSE);
+ LLRect morph_view_rect = full_window;
+ morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
+ morph_view_rect.mTop = full_window.mTop - 32;
+ if (gMorphView)
+ mRootView->removeChild(gMorphView, TRUE);
+
+ gMorphView = new LLMorphView(std::string("gMorphView"), morph_view_rect );
+ mRootView->addChild(gMorphView);
+ gMorphView->setVisible(FALSE);
- // *Note: this is where gFloaterMute used to be initialized.
+ // *Note: this is where gFloaterMute used to be initialized.
- LLWorldMapView::initClass();
+ LLWorldMapView::initClass();
- adjust_rect_centered_partial_zoom("FloaterWorldMapRect2", full_window);
+ adjust_rect_centered_partial_zoom("FloaterWorldMapRect2", full_window);
+ if (!gFloaterWorldMap)
+ {
gFloaterWorldMap = new LLFloaterWorldMap();
gFloaterWorldMap->setVisible(FALSE);
+ }
- //
- // Tools for building
- //
-
- // Toolbox floater
- init_menus();
+ //
+ // Tools for building
+ //
+ // Toolbox floater
+ init_menus();
+ if (!gFloaterTools)
+ {
gFloaterTools = new LLFloaterTools();
gFloaterTools->setVisible(FALSE);
+ }
+ if (!gStatusBar)
+ {
// Status bar
S32 menu_bar_height = gMenuBarView->getRect().getHeight();
- LLRect root_rect = getRootView()->getRect();
+ LLRect root_rect = mRootView->getRect();
LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height);
gStatusBar = new LLStatusBar(std::string("status"), status_rect);
gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
-
+
gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE);
gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight());
// sync bg color with menu bar
gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() );
+ mRootView->addChild(gStatusBar);
+ }
- LLFloaterChatterBox::createInstance(LLSD());
+ LLFloaterChatterBox::createInstance(LLSD());
- getRootView()->addChild(gStatusBar);
- // menu holder appears on top to get first pass at all mouse events
- getRootView()->sendChildToFront(gMenuHolder);
- }
+ // menu holder appears on top to get first pass at all mouse events
+
+ mRootView->sendChildToFront(gMenuHolder);
}
// Destroy the UI
@@ -5136,7 +5149,6 @@ void LLBottomPanel::draw()
void* LLBottomPanel::createHUD(void* data)
{
- delete gHUDView;
gHUDView = new LLHUDView();
return gHUDView;
}
@@ -5144,14 +5156,12 @@ void* LLBottomPanel::createHUD(void* data)
void* LLBottomPanel::createOverlayBar(void* data)
{
- delete gOverlayBar;
gOverlayBar = new LLOverlayBar();
return gOverlayBar;
}
void* LLBottomPanel::createToolBar(void* data)
{
- delete gToolBar;
gToolBar = new LLToolBar();
return gToolBar;
}
diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp
index 3d2523e..999a609 100644
--- a/linden/indra/newview/llvoavatar.cpp
+++ b/linden/indra/newview/llvoavatar.cpp
@@ -691,7 +691,11 @@ LLVOAvatar::LLVOAvatar(
mTexEyeColor( NULL ),
mNeedsSkin(FALSE),
mUpdatePeriod(1),
- mFullyLoadedInitialized(FALSE)
+// mFullyLoadedInitialized(FALSE)
+ mPreviousFullyLoaded(FALSE),
+ mVisibleChat( FALSE ),
+ mFullyLoadedInitialized(FALSE),
+ mFullyLoaded(FALSE)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
@@ -1807,6 +1811,10 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
+ //this can get called with null info on startup sometimes
+ if (!info)
+ return FALSE;
+
//-------------------------------------------------------------------------
// allocate joints
//-------------------------------------------------------------------------
@@ -2174,9 +2182,10 @@ void LLVOAvatar::buildCharacter()
LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(),
NULL, &object_selected_and_point_valid,
&attach_label, attachment);
+if (item){
item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", curiter->first);
gAttachSubMenu->append(item);
-
+}
gDetachSubMenu->append(new LLMenuItemCallGL(attachment->getName(),
&handle_detach_from_avatar, object_attached, &detach_label, attachment));
--
cgit v1.1
From 8840e40ed017d88eb9a3b830cfca818b0627b65b Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Wed, 9 Sep 2009 12:14:15 -0500
Subject: Commented out Linux tarball building.
It's a waste of time to package after every compile.
---
ChangeLog.txt | 8 +++++++
linden/indra/newview/viewer_manifest.py | 42 +++++++++++++++++----------------
2 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/ChangeLog.txt b/ChangeLog.txt
index bb88684..76e06ed 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,11 @@
+2009-09-09 Jacek Antonelli
+
+ * Commented out Linux tarball building.
+ It's a waste of time to package after every compile.
+
+ modified: linden/indra/newview/viewer_manifest.py
+
+
2009-09-08 McCabe Maxsted
* Created my own version of Emerald's chat channel tool.
diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py
index 5da0256..6ae5b80 100755
--- a/linden/indra/newview/viewer_manifest.py
+++ b/linden/indra/newview/viewer_manifest.py
@@ -746,26 +746,28 @@ class LinuxManifest(ViewerManifest):
self.package_file = installer_name + '.tar.bz2'
- if("package" in self.args['actions'] or
- "unpacked" in self.args['actions']):
-
- # temporarily move directory tree so that it has the right
- # name in the tarfile
- self.run_command("mv %(dst)s %(inst)s" % {
- 'dst': self.get_dst_prefix(),
- 'inst': self.build_path_of(installer_name)})
- try:
- # --numeric-owner hides the username of the builder for
- # security etc.
- self.run_command('tar -C %(dir)s --numeric-owner -cjf '
- '%(inst_path)s.tar.bz2 %(inst_name)s' % {
- 'dir': self.get_build_prefix(),
- 'inst_name': installer_name,
- 'inst_path':self.build_path_of(installer_name)})
- finally:
- self.run_command("mv %(inst)s %(dst)s" % {
- 'dst': self.get_dst_prefix(),
- 'inst': self.build_path_of(installer_name)})
+ # Disabled for now. It's a waste of time to package every compile.
+
+ # if("package" in self.args['actions'] or
+ # "unpacked" in self.args['actions']):
+ #
+ # # temporarily move directory tree so that it has the right
+ # # name in the tarfile
+ # self.run_command("mv %(dst)s %(inst)s" % {
+ # 'dst': self.get_dst_prefix(),
+ # 'inst': self.build_path_of(installer_name)})
+ # try:
+ # # --numeric-owner hides the username of the builder for
+ # # security etc.
+ # self.run_command('tar -C %(dir)s --numeric-owner -cjf '
+ # '%(inst_path)s.tar.bz2 %(inst_name)s' % {
+ # 'dir': self.get_build_prefix(),
+ # 'inst_name': installer_name,
+ # 'inst_path':self.build_path_of(installer_name)})
+ # finally:
+ # self.run_command("mv %(inst)s %(dst)s" % {
+ # 'dst': self.get_dst_prefix(),
+ # 'inst': self.build_path_of(installer_name)})
class Linux_i686Manifest(LinuxManifest):
--
cgit v1.1
From f57eabefa1291f4e047aa03416c9c544413b9f0e Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Thu, 10 Sep 2009 02:31:50 -0500
Subject: Fixed line endings on hippo and grid manager files.
---
.../indra/newview/app_settings/default_grids.xml | 102 +-
linden/indra/newview/hippoGridManager.cpp | 1194 ++++++++++----------
linden/indra/newview/hippoGridManager.h | 342 +++---
linden/indra/newview/hippoLimits.cpp | 108 +-
linden/indra/newview/hippoLimits.h | 66 +-
linden/indra/newview/hippoRestRequest.cpp | 108 +-
linden/indra/newview/hippoRestRequest.h | 32 +-
linden/indra/newview/hippoUpdate.cpp | 184 +--
linden/indra/newview/hippoUpdate.h | 24 +-
9 files changed, 1080 insertions(+), 1080 deletions(-)
diff --git a/linden/indra/newview/app_settings/default_grids.xml b/linden/indra/newview/app_settings/default_grids.xml
index f4feb0c..dabcb0b 100644
--- a/linden/indra/newview/app_settings/default_grids.xml
+++ b/linden/indra/newview/app_settings/default_grids.xml
@@ -1,51 +1,51 @@
-
-
-
-
-
-
- default_grids_version0
-
-
-
-
- gridnickosgrid
- gridnameOSGrid
- platformOpenSim
- loginurihttp://osgrid.org:8002/
- loginpagehttp://osgrid.org/loginscreen.php
- helperurihttp://osgrid.org/
- websitehttp://osgrid.org/
- supporthttp://osgrid.org/
- registerhttp://osgrid.org/index.php?page=create
- passwordhttp://osgrid.org/index.php?page=change
-
-
-
-
- gridnicksecondlife
- gridnameSecond Life
- platformSecondLife
- loginurihttps://login.agni.lindenlab.com/cgi-bin/login.cgi
- loginpagehttp://secondlife.com/app/login/
- helperurihttps://secondlife.com/helpers/
- websitehttp://secondlife.com/
- supporthttp://secondlife.com/support/
- registerhttp://secondlife.com/registration/
- passwordhttp://secondlife.com/account/request.php
-
-
-
-
- gridnicklocal
- gridnameLocal Host
- platformOpenSim
- loginurihttp://127.0.0.1:9000/
- helperurihttp://127.0.0.1:9000/
-
-
-
-
+
+
+
+
+
+
+ default_grids_version0
+
+
+
+
+ gridnickosgrid
+ gridnameOSGrid
+ platformOpenSim
+ loginurihttp://osgrid.org:8002/
+ loginpagehttp://osgrid.org/loginscreen.php
+ helperurihttp://osgrid.org/
+ websitehttp://osgrid.org/
+ supporthttp://osgrid.org/
+ registerhttp://osgrid.org/index.php?page=create
+ passwordhttp://osgrid.org/index.php?page=change
+
+
+
+
+ gridnicksecondlife
+ gridnameSecond Life
+ platformSecondLife
+ loginurihttps://login.agni.lindenlab.com/cgi-bin/login.cgi
+ loginpagehttp://secondlife.com/app/login/
+ helperurihttps://secondlife.com/helpers/
+ websitehttp://secondlife.com/
+ supporthttp://secondlife.com/support/
+ registerhttp://secondlife.com/registration/
+ passwordhttp://secondlife.com/account/request.php
+
+
+
+
+ gridnicklocal
+ gridnameLocal Host
+ platformOpenSim
+ loginurihttp://127.0.0.1:9000/
+ helperurihttp://127.0.0.1:9000/
+
+
+
+
diff --git a/linden/indra/newview/hippoGridManager.cpp b/linden/indra/newview/hippoGridManager.cpp
index 8415adb..19ed2c4 100644
--- a/linden/indra/newview/hippoGridManager.cpp
+++ b/linden/indra/newview/hippoGridManager.cpp
@@ -1,597 +1,597 @@
-
-
-#include "hippoGridManager.h"
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include