Skip to content
Snippets Groups Projects
llstartup.cpp 101 KiB
Newer Older
James Cook's avatar
James Cook committed
/** 
 * @file llstartup.cpp
 * @brief startup routines.
 *
 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
James Cook's avatar
James Cook committed
 */

#include "llviewerprecompiledheaders.h"

#include "llstartup.h"

#if LL_WINDOWS
#	include <process.h>		// _spawnl()
James Cook's avatar
James Cook committed
#else
#	include <sys/stat.h>		// mkdir()
James Cook's avatar
James Cook committed
#endif

#include "llviewermedia_streamingaudio.h"
#include "llaudioengine.h"
James Cook's avatar
James Cook committed

# include "llaudioengine_fmod.h"
James Cook's avatar
James Cook committed
#endif

#ifdef LL_OPENAL
#include "llaudioengine_openal.h"
James Cook's avatar
James Cook committed
#include "llcachename.h"
#include "lldir.h"
#include "llerrorcontrol.h"
#include "llfloaterreg.h"
James Cook's avatar
James Cook committed
#include "llfocusmgr.h"
#include "lllocationhistory.h"
#include "llimageworker.h"
James Cook's avatar
James Cook committed
#include "llloginflags.h"
#include "llmd5.h"
#include "llmemorystream.h"
Josh Bell's avatar
Josh Bell committed
#include "llmoveview.h"
#include "llteleporthistory.h"
James Cook's avatar
James Cook committed
#include "llregionhandle.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llsdutil_math.h"
James Cook's avatar
James Cook committed
#include "llsecondlifeurls.h"
#include "llstring.h"
#include "lluserrelations.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
James Cook's avatar
James Cook committed
#include "llvfs.h"
#include "llxorcipher.h"	// saved password, MAC address
James Cook's avatar
James Cook committed
#include "message.h"
#include "v3math.h"

#include "llagent.h"
#include "llagentpicksinfo.h"
#include "llagentwearables.h"
James Cook's avatar
James Cook committed
#include "llagentpilot.h"
#include "llfloateravatarpicker.h"
#include "llcallbacklist.h"
#include "llcallingcard.h"
#include "llconsole.h"
#include "llcontainerview.h"
#include "lldebugview.h"
#include "lldrawable.h"
#include "lleventnotifier.h"
#include "llface.h"
#include "llfeaturemanager.h"
James Cook's avatar
James Cook committed
#include "llfloaterhud.h"
James Cook's avatar
James Cook committed
#include "llfloaterland.h"
#include "llfloaterpreference.h"
James Cook's avatar
James Cook committed
#include "llfloatertopobjects.h"
#include "llfloaterworldmap.h"
#include "llgesturemgr.h"
#include "llgroupmgr.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
#include "llhttpclient.h"
#include "llimagebmp.h"
#include "llinventorybridge.h"
James Cook's avatar
James Cook committed
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
James Cook's avatar
James Cook committed
#include "llkeyboard.h"
#include "llloginhandler.h"			// gLoginHandler, SLURL support
#include "lllogininstance.h" // Host the login module.
James Cook's avatar
James Cook committed
#include "llpanellogin.h"
#include "llmutelist.h"
#include "llavatarpropertiesprocessor.h"
James Cook's avatar
James Cook committed
#include "llpanelclassified.h"
#include "llpanelpick.h"
#include "llpanelgrouplandmoney.h"
#include "llpanelgroupnotices.h"
#include "llpreview.h"
#include "llpreviewscript.h"
#include "llproductinforequest.h"
James Cook's avatar
James Cook committed
#include "llselectmgr.h"
#include "llsky.h"
#include "llsidetray.h"
James Cook's avatar
James Cook committed
#include "llstatview.h"
#include "llstatusbar.h"		// sendMoneyBalanceRequest(), owns L$ balance
James Cook's avatar
James Cook committed
#include "llsurface.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
James Cook's avatar
James Cook committed
#include "lltoolmgr.h"
James Cook's avatar
James Cook committed
#include "llui.h"
#include "llslurl.h"
Josh Bell's avatar
Josh Bell committed
#include "llurlhistory.h"
James Cook's avatar
James Cook committed
#include "llurlwhitelist.h"
James Cook's avatar
James Cook committed
#include "llviewerassetstorage.h"
#include "llviewercamera.h"
#include "llviewerdisplay.h"
James Cook's avatar
James Cook committed
#include "llviewergesture.h"
#include "llviewertexturelist.h"
Josh Bell's avatar
Josh Bell committed
#include "llviewermedia.h"
James Cook's avatar
James Cook committed
#include "llviewermenu.h"
#include "llviewermessage.h"
#include "llviewernetwork.h"
#include "llviewerobjectlist.h"
Josh Bell's avatar
Josh Bell committed
#include "llviewerparcelmedia.h"
James Cook's avatar
James Cook committed
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewerthrottle.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
James Cook's avatar
James Cook committed
#include "llvoclouds.h"
James Cook's avatar
James Cook committed
#include "llworld.h"
#include "llworldmapmessage.h"
James Cook's avatar
James Cook committed
#include "llxfermanager.h"
#include "pipeline.h"
James Cook's avatar
James Cook committed
#include "llfasttimerview.h"
James Cook's avatar
James Cook committed
#include "llweb.h"
#include "llvoiceclient.h"
#include "llnamelistctrl.h"
#include "llnamebox.h"
#include "llnameeditor.h"
#include "llpostprocess.h"
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
Don Kjer's avatar
Don Kjer committed
#include "llagentlanguage.h"
#include "llwearable.h"
#include "llinventorybridge.h"
#include "llvoicechannel.h"
Don Kjer's avatar
Don Kjer committed

#include "lllogin.h"
#include "llstartuplistener.h"
James Cook's avatar
James Cook committed
#if LL_WINDOWS
#include "lldxhardware.h"
#endif

//
// exported globals
//
bool gAgentMovementCompleted = false;
James Cook's avatar
James Cook committed

std::string SCREEN_HOME_FILENAME = "screen_home.bmp";
std::string SCREEN_LAST_FILENAME = "screen_last.bmp";
James Cook's avatar
James Cook committed

LLPointer<LLViewerTexture> gStartTexture;
James Cook's avatar
James Cook committed
//
// Imported globals
//
extern S32 gStartImageWidth;
extern S32 gStartImageHeight;

//
// local globals
//
static bool gGotUseCircuitCodeAck = false;
static std::string sInitialOutfit;
static std::string sInitialOutfitGender;	// "male" or "female"
static boost::signals2::connection sWearablesLoadedCon;
James Cook's avatar
James Cook committed

static bool gUseCircuitCallbackCalled = false;
James Cook's avatar
James Cook committed

EStartupState LLStartUp::gStartupState = STATE_FIRST;
LLSLURL LLStartUp::sStartSLURL;
static LLPointer<LLCredential> gUserCredential;
static std::string gDisplayName;
static BOOL gRememberPassword = TRUE;     

static U64 gFirstSimHandle = 0;
static LLHost gFirstSim;
static std::string gFirstSimSeedCap;
static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f);
static std::string gAgentStartLocation = "safe";

boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener());
James Cook's avatar
James Cook committed
//
// local function declaration
//

void login_show();
void login_callback(S32 option, void* userdata);
void show_first_run_dialog();
Kent Quirk's avatar
Kent Quirk committed
bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
Kent Quirk's avatar
Kent Quirk committed
bool login_alert_status(const LLSD& notification, const LLSD& response);
James Cook's avatar
James Cook committed
void login_packet_failed(void**, S32 result);
void use_circuit_callback(void**, S32 result);
void register_viewer_callbacks(LLMessageSystem* msg);
void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32);
Kent Quirk's avatar
Kent Quirk committed
bool callback_choose_gender(const LLSD& notification, const LLSD& response);
James Cook's avatar
James Cook committed
void init_start_screen(S32 location_id);
void release_start_screen();
LLSD transform_cert_args(LLPointer<LLCertificate> cert);
void general_cert_done(const LLSD& notification, const LLSD& response);
void trust_cert_done(const LLSD& notification, const LLSD& response);
void apply_udp_blacklist(const std::string& csv);
bool process_login_success_response();
void transition_back_to_login_panel(const std::string& emsg);
James Cook's avatar
James Cook committed

void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group)
{
	LLNameListCtrl::refreshAll(id, firstname, lastname, is_group);
	LLNameBox::refreshAll(id, firstname, lastname, is_group);
	LLNameEditor::refreshAll(id, firstname, lastname, is_group);
	
	// TODO: Actually be intelligent about the refresh.
	// For now, just brute force refresh the dialogs.
	dialog_refresh_all();
}

James Cook's avatar
James Cook committed
//
// exported functionality
//

//
// local classes
//

namespace
{
	class LLNullHTTPSender : public LLHTTPSender
	{
		virtual void send(const LLHost& host, 
						  const std::string& message, const LLSD& body, 
						  LLHTTPClient::ResponderPtr response) const
		{
			LL_WARNS("AppInit") << " attemped to send " << message << " to " << host
					<< " with null sender" << LL_ENDL;
void update_texture_fetch()
{
	LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
	LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
	LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
	gTextureList.updateImages(0.10f);
James Cook's avatar
James Cook committed

// Returns false to skip other idle processing. Should only return
// true when all initialization done.
bool idle_startup()
James Cook's avatar
James Cook committed
{
	LLMemType mt1(LLMemType::MTYPE_STARTUP);
	
	const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay");
	static LLTimer timeout;
	static S32 timeout_count = 0;

	static LLTimer login_time;

	// until this is encapsulated, this little hack for the
	// auth/transform loop will do.
	static F32 progress = 0.10f;

	static std::string auth_desc;
	static std::string auth_message;

	static LLVector3 initial_sun_direction(1.f, 0.f, 0.f);
	static LLVector3 agent_start_position_region(10.f, 10.f, 10.f);		// default for when no space server

	// last location by default
	static S32  agent_location_id = START_LOCATION_ID_LAST;
	static S32  location_which = START_LOCATION_ID_LAST;

	static bool show_connect_box = true;
James Cook's avatar
James Cook committed

	//static bool stipend_since_login = false;
James Cook's avatar
James Cook committed

	// HACK: These are things from the main loop that usually aren't done
	// until initialization is complete, but need to be done here for things
	// to work.
	gIdleCallbacks.callFunctions();
	gViewerWindow->updateUI();
James Cook's avatar
James Cook committed
	LLMortician::updateClass();

	const std::string delims (" ");
	std::string system;
	int begIdx, endIdx;
	std::string osString = LLAppViewer::instance()->getOSInfo().getOSStringSimple();

	begIdx = osString.find_first_not_of (delims);
	endIdx = osString.find_first_of (delims, begIdx);
	system = osString.substr (begIdx, endIdx - begIdx);
	system += "Locale";

	LLStringUtil::setLocale (LLTrans::getString(system));

James Cook's avatar
James Cook committed
	{
		//note: Removing this line will cause incorrect button size in the login screen. -- bao.
		gTextureList.updateImages(0.01f) ;
	if ( STATE_FIRST == LLStartUp::getStartupState() )
James Cook's avatar
James Cook committed
	{
		gViewerWindow->showCursor(); 
James Cook's avatar
James Cook committed
		gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);

		/////////////////////////////////////////////////
		//
		// Initialize stuff that doesn't need data from simulators
		if (LLFeatureManager::getInstance()->isSafe())
James Cook's avatar
James Cook committed
		{
			LLNotificationsUtil::add("DisplaySetToSafe");
James Cook's avatar
James Cook committed
		}
		else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) &&
				 (gSavedSettings.getS32("LastFeatureVersion") != 0))
James Cook's avatar
James Cook committed
		{
			LLNotificationsUtil::add("DisplaySetToRecommended");
		else if ((gSavedSettings.getS32("LastGPUClass") != LLFeatureManager::getInstance()->getGPUClass()) &&
				 (gSavedSettings.getS32("LastGPUClass") != -1))
		{
			LLNotificationsUtil::add("DisplaySetToRecommended");
		}
			LLNotificationsUtil::add(gViewerWindow->getInitAlert());
James Cook's avatar
James Cook committed
		}
		gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());
		gSavedSettings.setS32("LastGPUClass", LLFeatureManager::getInstance()->getGPUClass());
James Cook's avatar
James Cook committed

		// load dynamic GPU/feature tables from website (S3)
		LLFeatureManager::getInstance()->fetchHTTPTables();
		
		std::string xml_file = LLUI::locateSkin("xui_version.xml");
James Cook's avatar
James Cook committed
		LLXMLNodePtr root;
		bool xml_ok = false;
		if (LLXMLNode::parseFile(xml_file, root, NULL))
		{
			if( (root->hasName("xui_version") ) )
			{
				std::string value = root->getValue();
James Cook's avatar
James Cook committed
				F32 version = 0.0f;
				LLStringUtil::convertToF32(value, version);
James Cook's avatar
James Cook committed
				if (version >= 1.0f)
				{
					xml_ok = true;
				}
			}
		}
		if (!xml_ok)
		{
Kent Quirk's avatar
Kent Quirk committed
			// If XML is bad, there's a good possibility that notifications.xml is ALSO bad.
			// If that's so, then we'll get a fatal error on attempting to load it, 
			// which will display a nontranslatable error message that says so.
			// Otherwise, we'll display a reasonable error message that IS translatable.
			LLAppViewer::instance()->earlyExit("BadInstallation");
James Cook's avatar
James Cook committed
		}
		//
		// Statistics stuff
		//

		// Load autopilot and stats stuff
		gAgentPilot.load(gSavedSettings.getString("StatsPilotFile"));
James Cook's avatar
James Cook committed

		//gErrorStream.setTime(gSavedSettings.getBOOL("LogTimestamps"));

		// Load the throttle settings
		gViewerThrottle.load();

		if (ll_init_ares() == NULL || !gAres->isInitialized())
Kent Quirk's avatar
Kent Quirk committed
			std::string diagnostic = "Could not start address resolution system";
			LL_WARNS("AppInit") << diagnostic << LL_ENDL;
			LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
James Cook's avatar
James Cook committed
		//
		// Initialize messaging system
		//
		LL_DEBUGS("AppInit") << "Initializing messaging system..." << LL_ENDL;
James Cook's avatar
James Cook committed

		std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg");

		LLFILE* found_template = NULL;
		found_template = LLFile::fopen(message_template_path, "r");		/* Flawfinder: ignore */
		
		#if LL_WINDOWS
			// On the windows dev builds, unpackaged, the message_template.msg 
			// file will be located in:
			// build-vc**/newview/<config>/app_settings
			if (!found_template)
			{
				message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg");
				found_template = LLFile::fopen(message_template_path.c_str(), "r");		/* Flawfinder: ignore */
			}	
		#elif LL_DARWIN
			// On Mac dev builds, message_template.msg lives in:
			// indra/build-*/newview/<config>/Second Life/Contents/Resources/app_settings
			if (!found_template)
			{
				message_template_path =
					gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE,
												   "../Resources/app_settings",
												   "message_template.msg");
				found_template = LLFile::fopen(message_template_path.c_str(), "r");		/* Flawfinder: ignore */
			}		
James Cook's avatar
James Cook committed
		if (found_template)
		{
			fclose(found_template);

			U32 port = gSavedSettings.getU32("UserConnectionPort");

			if ((NET_USE_OS_ASSIGNED_PORT == port) &&   // if nothing specified on command line (-port)
			    (gSavedSettings.getBOOL("ConnectionPortEnabled")))
			  {
			    port = gSavedSettings.getU32("ConnectionPort");
			  }

			LLHTTPSender::setDefaultSender(new LLNullHTTPSender());

			// TODO parameterize 
			const F32 circuit_heartbeat_interval = 5;
			const F32 circuit_timeout = 100;

			const LLUseCircuitCodeResponder* responder = NULL;
			bool failure_is_fatal = true;
			
James Cook's avatar
James Cook committed
			if(!start_messaging_system(
				   message_template_path,
				   LLVersionInfo::getMajor(),
				   LLVersionInfo::getMinor(),
				   LLVersionInfo::getPatch(),
James Cook's avatar
James Cook committed
				   FALSE,
				   std::string(),
				   responder,
				   failure_is_fatal,
				   circuit_heartbeat_interval,
				   circuit_timeout))
James Cook's avatar
James Cook committed
			{
Kent Quirk's avatar
Kent Quirk committed
				std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode());
				LL_WARNS("AppInit") << diagnostic << LL_ENDL;
				LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
James Cook's avatar
James Cook committed
			}

			#if LL_WINDOWS
				// On the windows dev builds, unpackaged, the message.xml file will 
				// be located in indra/build-vc**/newview/<config>/app_settings.
				std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml");
							
				if (!LLFile::isfile(message_path.c_str())) 
				{
					LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", ""));
				}
				else
				{
					LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
				}
			#else			
				LLMessageConfig::initClass("viewer", gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
			#endif

James Cook's avatar
James Cook committed
		}
		else
		{
			LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().with("PATH", message_template_path));
James Cook's avatar
James Cook committed
		}

		if(gMessageSystem && gMessageSystem->isOK())
		{
			// Initialize all of the callbacks in case of bad message
			// system data
			LLMessageSystem* msg = gMessageSystem;
			msg->setExceptionFunc(MX_UNREGISTERED_MESSAGE,
								  invalid_message_callback,
								  NULL);
			msg->setExceptionFunc(MX_PACKET_TOO_SHORT,
								  invalid_message_callback,
								  NULL);

			// running off end of a packet is now valid in the case
			// when a reader has a newer message template than
			// the sender
			/*msg->setExceptionFunc(MX_RAN_OFF_END_OF_PACKET,
James Cook's avatar
James Cook committed
								  invalid_message_callback,
James Cook's avatar
James Cook committed
			msg->setExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE,
								  invalid_message_callback,
								  NULL);

			if (gSavedSettings.getBOOL("LogMessages"))
James Cook's avatar
James Cook committed
			{
				LL_DEBUGS("AppInit") << "Message logging activated!" << LL_ENDL;
James Cook's avatar
James Cook committed
				msg->startLogging();
			}

			// start the xfer system. by default, choke the downloads
			// a lot...
			const S32 VIEWER_MAX_XFER = 3;
			start_xfer_manager(gVFS);
			gXferManager->setMaxIncomingXfers(VIEWER_MAX_XFER);
			F32 xfer_throttle_bps = gSavedSettings.getF32("XferThrottle");
			if (xfer_throttle_bps > 1.f)
			{
				gXferManager->setUseAckThrottling(TRUE);
				gXferManager->setAckThrottleBPS(xfer_throttle_bps);
			}
			gAssetStorage = new LLViewerAssetStorage(msg, gXferManager, gVFS, gStaticVFS);
James Cook's avatar
James Cook committed


			F32 dropPercent = gSavedSettings.getF32("PacketDropPercentage");
			msg->mPacketRing.setDropPercentage(dropPercent);

            F32 inBandwidth = gSavedSettings.getF32("InBandwidth"); 
            F32 outBandwidth = gSavedSettings.getF32("OutBandwidth"); 
			if (inBandwidth != 0.f)
James Cook's avatar
James Cook committed
			{
				LL_DEBUGS("AppInit") << "Setting packetring incoming bandwidth to " << inBandwidth << LL_ENDL;
James Cook's avatar
James Cook committed
				msg->mPacketRing.setUseInThrottle(TRUE);
				msg->mPacketRing.setInBandwidth(inBandwidth);
James Cook's avatar
James Cook committed
			}
			if (outBandwidth != 0.f)
James Cook's avatar
James Cook committed
			{
				LL_DEBUGS("AppInit") << "Setting packetring outgoing bandwidth to " << outBandwidth << LL_ENDL;
James Cook's avatar
James Cook committed
				msg->mPacketRing.setUseOutThrottle(TRUE);
				msg->mPacketRing.setOutBandwidth(outBandwidth);
		LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL;
		
James Cook's avatar
James Cook committed
		//-------------------------------------------------
		// Init audio, which may be needed for prefs dialog
		// or audio cues in connection UI.
		//-------------------------------------------------

		if (FALSE == gSavedSettings.getBOOL("NoAudio"))
James Cook's avatar
James Cook committed
		{
			gAudiop = NULL;

#ifdef LL_OPENAL
			if (!gAudiop
#if !LL_WINDOWS
			    && NULL == getenv("LL_BAD_OPENAL_DRIVER")
#endif // !LL_WINDOWS
			    )
			{
				gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL();
			}
#endif

#ifdef LL_FMOD			
			if (!gAudiop
#if !LL_WINDOWS
			    && NULL == getenv("LL_BAD_FMOD_DRIVER")
#endif // !LL_WINDOWS
			    )
			{
				gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD();
			}
James Cook's avatar
James Cook committed
#endif

			if (gAudiop)
			{
#if LL_WINDOWS
				// FMOD on Windows needs the window handle to stop playing audio
				// when window is minimized. JC
				void* window_handle = (HWND)gViewerWindow->getPlatformWindow();
James Cook's avatar
James Cook committed
#else
				void* window_handle = NULL;
#endif
				bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle);
				if(init)
				{
					gAudiop->setMuted(TRUE);
				}
				else
James Cook's avatar
James Cook committed
				{
					LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL;
					delete gAudiop;
					gAudiop = NULL;
James Cook's avatar
James Cook committed
				}

				if (gAudiop)
				{
					// if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins
					if (NULL == gAudiop->getStreamingAudioImpl())
					{
						LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL;
						gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins());
					}
				}
James Cook's avatar
James Cook committed
			}
		}
		
		LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL;
		
James Cook's avatar
James Cook committed
		if (LLTimer::knownBadTimer())
		{
			LL_WARNS("AppInit") << "Unreliable timers detected (may be bad PCI chipset)!!" << LL_ENDL;
		if (gUserCredential.isNull())
		{
			gUserCredential = gLoginHandler.initializeLoginInfo();
		if (gUserCredential.isNull())
			show_connect_box = TRUE;
		}
		else if (gSavedSettings.getBOOL("AutoLogin"))  
		{
			gRememberPassword = TRUE;
			gSavedSettings.setBOOL("RememberPassword", TRUE);                                                      
			show_connect_box = false;    			
		}
		else 
		{
			gRememberPassword = gSavedSettings.getBOOL("RememberPassword");
			show_connect_box = TRUE;
James Cook's avatar
James Cook committed
		}
		// Go to the next startup state
		LLStartUp::setStartupState( STATE_BROWSER_INIT );
		return FALSE;
	if (STATE_BROWSER_INIT == LLStartUp::getStartupState())
		LL_DEBUGS("AppInit") << "STATE_BROWSER_INIT" << LL_ENDL;
		std::string msg = LLTrans::getString("LoginInitializingBrowser");
		set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str());
Josh Bell's avatar
Josh Bell committed
		display_startup();
		// LLViewerMedia::initBrowser();
		LLStartUp::setStartupState( STATE_LOGIN_SHOW );
	if (STATE_LOGIN_SHOW == LLStartUp::getStartupState())
	{
		LL_DEBUGS("AppInit") << "Initializing Window" << LL_ENDL;
James Cook's avatar
James Cook committed
		gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);

		timeout_count = 0;

		if (show_connect_box)
James Cook's avatar
James Cook committed
		{
			// Load all the name information out of the login view
			// NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't
			// show the login view until login_show() is called below.  
			if (gUserCredential.isNull())                                                                          
			{                                                                                                      
				gUserCredential = gLoginHandler.initializeLoginInfo();                 
			}     
James Cook's avatar
James Cook committed
			{
				LL_ERRS("AppInit") << "Need to autologin or use command line with norender!" << LL_ENDL;
			}
			// Make sure the process dialog doesn't hide things
			gViewerWindow->setShowProgress(FALSE);
James Cook's avatar
James Cook committed

			// Show the login dialog
			login_show();
			// connect dialog is already shown, so fill in the names
			if (gUserCredential.notNull())                                                                         
			{                                                                                                      
				LLPanelLogin::setFields( gUserCredential, gRememberPassword);                                  
			}     
			LLPanelLogin::giveFocus();
James Cook's avatar
James Cook committed

			gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);

			LLStartUp::setStartupState( STATE_LOGIN_WAIT );		// Wait for user input
James Cook's avatar
James Cook committed
		}
		else
		{
			// skip directly to message template verification
			LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
James Cook's avatar
James Cook committed
		}

		// *NOTE: This is where LLViewerParcelMgr::getInstance() used to get allocated before becoming LLViewerParcelMgr::getInstance().

		// *NOTE: This is where gHUDManager used to bet allocated before becoming LLHUDManager::getInstance().

		// *NOTE: This is where gMuteList used to get allocated before becoming LLMuteList::getInstance().
		// Login screen needs menus for preferences, but we can enter
		// this startup phase more than once.
		if (gLoginMenuBarView == NULL)
		}
		
		gViewerWindow->setNormalControlsVisible( FALSE );	
		gLoginMenuBarView->setVisible( TRUE );
Josh Bell's avatar
Josh Bell committed
		gLoginMenuBarView->setEnabled( TRUE );
James Cook's avatar
James Cook committed

		// Hide the splash screen
		LLSplashScreen::hide();

		// Push our window frontmost
		gViewerWindow->getWindow()->show();
		display_startup();

		// DEV-16927.  The following code removes errant keystrokes that happen while the window is being 
		// first made visible.
#ifdef _WIN32
		MSG msg;
		while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) );
#endif
James Cook's avatar
James Cook committed
		timeout.reset();
	if (STATE_LOGIN_WAIT == LLStartUp::getStartupState())
James Cook's avatar
James Cook committed
	{
		// Don't do anything.  Wait for the login view to call the login_callback,
		// which will push us to the next state.

		// Sleep so we don't spin the CPU
		ms_sleep(1);
	if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
James Cook's avatar
James Cook committed
	{
Steven Bennetts's avatar
Steven Bennetts committed
		// Move the progress view in front of the UI immediately when login is performed
		// this allows not to see main menu after Alt+Tab was pressed while login. EXT-744.
		gViewerWindow->moveProgressViewToFront();

		//reset the values that could have come in from a slurl
		// DEV-42215: Make sure they're not empty -- gUserCredential
		// might already have been set from gSavedSettings, and it's too bad
		// to overwrite valid values with empty strings.
James Cook's avatar
James Cook committed
		if (show_connect_box)
		{
			// TODO if not use viewer auth
			// Load all the name information out of the login view
			LLPanelLogin::getFields(gUserCredential, gRememberPassword); 
James Cook's avatar
James Cook committed
			// HACK: Try to make not jump on login
			gKeyboard->resetKeys();
		}

		// save the credentials                                                                                        
		std::string userid = "unknown";                                                                                
		if(gUserCredential.notNull())                                                                                  
		{  
			userid = gUserCredential->userID();                                                                    
			gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);  
James Cook's avatar
James Cook committed
		}
		gSavedSettings.setBOOL("RememberPassword", gRememberPassword);                                                 
		LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;                                           
		gDebugInfo["LoginName"] = userid;                                                                              
         
James Cook's avatar
James Cook committed
		// create necessary directories
		// *FIX: these mkdir's should error check
		gDirUtilp->setLindenUserDir(userid);
		LLFile::mkdir(gDirUtilp->getLindenUserDir());
		// Set PerAccountSettingsFile to the default value.
		std::string per_account_settings_file = LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount");
		gSavedSettings.setString("PerAccountSettingsFile",
			gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, 
				LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")));
James Cook's avatar
James Cook committed

		// Note: can't store warnings files per account because some come up before login
		
		// Overwrite default user settings with user settings								 
		LLAppViewer::instance()->loadSettingsFromDirectory("Account");
James Cook's avatar
James Cook committed

		// Need to set the LastLogoff time here if we don't have one.  LastLogoff is used for "Recent Items" calculation
		// and startup time is close enough if we don't have a real value.
		if (gSavedPerAccountSettings.getU32("LastLogoff") == 0)
		{
			gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
		}

		//Default the path if one isn't set.
		// *NOTE: unable to check variable differ from "InstantMessageLogPath" because it was
		// provided in pre 2.0 viewer. See EXT-6661
		if (gSavedPerAccountSettings.getString("InstantMessageLogPath").empty())
James Cook's avatar
James Cook committed
		{
			gDirUtilp->setChatLogsDir(gDirUtilp->getOSUserAppDir());
			gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir());
James Cook's avatar
James Cook committed
		}
		else
		{
			gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));		
		}
		gDirUtilp->setPerAccountChatLogsDir(userid);  
James Cook's avatar
James Cook committed
		
		LLFile::mkdir(gDirUtilp->getChatLogsDir());
		LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
James Cook's avatar
James Cook committed

		//good a place as any to create user windlight directories
		std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", ""));
		LLFile::mkdir(user_windlight_path_name.c_str());		

		std::string user_windlight_skies_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
		LLFile::mkdir(user_windlight_skies_path_name.c_str());

		std::string user_windlight_water_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
		LLFile::mkdir(user_windlight_water_path_name.c_str());

		std::string user_windlight_days_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/days", ""));
		LLFile::mkdir(user_windlight_days_path_name.c_str());


James Cook's avatar
James Cook committed
		if (show_connect_box)
		{
			LLPanelLogin::closePanel();
Josh Bell's avatar
Josh Bell committed
		// Load URL History File
		LLURLHistory::loadFile("url_history.xml");
Steven Bennetts's avatar
Steven Bennetts committed
		// Load location history 
		LLLocationHistory::getInstance()->load();
		// Load Avatars icons cache
		LLAvatarIconIDCache::getInstance()->load();
		
		// Load media plugin cookies
		LLViewerMedia::loadCookieFile();
James Cook's avatar
James Cook committed
		//-------------------------------------------------
		// Handle startup progress screen
		//-------------------------------------------------

		// on startup the user can request to go to their home,
		// their last location, or some URL "-url //sim/x/y[/z]"
		// All accounts have both a home and a last location, and we don't support
		// more locations than that.  Choose the appropriate one.  JC
		switch (LLStartUp::getStartSLURL().getType())
		  {
		  case LLSLURL::LOCATION:
		    agent_location_id = START_LOCATION_ID_URL;
		    location_which = START_LOCATION_ID_LAST;
		    break;
		  case LLSLURL::LAST_LOCATION:
		    agent_location_id = START_LOCATION_ID_LAST;
		    location_which = START_LOCATION_ID_LAST;
		    break;
		  default:
		    agent_location_id = START_LOCATION_ID_HOME;
		    location_which = START_LOCATION_ID_HOME;
		    break;
		  }
James Cook's avatar
James Cook committed

		gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);

		if (!gNoRender)
		{
			init_start_screen(agent_location_id);
		}

		// Display the startup progress bar.
		gViewerWindow->setShowProgress(TRUE);
		gViewerWindow->setProgressCancelButtonVisible(TRUE, LLTrans::getString("Quit"));
James Cook's avatar
James Cook committed

		// Poke the VFS, which could potentially block for a while if
		// Windows XP is acting up
		set_startup_status(0.07f, LLTrans::getString("LoginVerifyingCache"), LLStringUtil::null);
James Cook's avatar
James Cook committed
		display_startup();

		gVFS->pokeFiles();

		LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
James Cook's avatar
James Cook committed

	if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
James Cook's avatar
James Cook committed
	{
		gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
		// Update progress status and the display loop.
		auth_desc = LLTrans::getString("LoginInProgress");
		set_startup_status(progress, auth_desc, auth_message);
James Cook's avatar
James Cook committed
		progress += 0.02f;
		display_startup();

		// Setting initial values...
		LLLoginInstance* login = LLLoginInstance::getInstance();
		login->setNotificationsInterface(LLNotifications::getInstance());
James Cook's avatar
James Cook committed
		{
			// HACK, skip optional updates if you're running drones
			login->setSkipOptionalUpdate(true);
		login->setUserInteraction(show_connect_box);
		login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
		login->setLastExecEvent(gLastExecEvent);
		login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance()));

		// This call to LLLoginInstance::connect() starts the 
		// authentication process.
		login->connect(gUserCredential);
		LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
		return FALSE;
	}

	if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState())
	{
		// If we get here we have gotten past the potential stall
		// in curl, so take "may appear frozen" out of progress bar. JC
		auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
		set_startup_status(progress, auth_desc, auth_message);

		LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
	if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) 
James Cook's avatar
James Cook committed
	{
		std::ostringstream emsg;
		emsg << LLTrans::getString("LoginFailed") << "\n";
		if(LLLoginInstance::getInstance()->authFailure())
		{
			LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
			                      << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
			LLSD response = LLLoginInstance::getInstance()->getResponse();