diff options
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r-- | indra/newview/llappviewer.cpp | 1512 |
1 files changed, 985 insertions, 527 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ce66bb6180..92a9b83bc5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2,31 +2,25 @@ * @file llappviewer.cpp * @brief The LLAppViewer class definitions * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -34,23 +28,23 @@ #include "llappviewer.h" -#include "llprimitive.h" - -#include "llversionviewer.h" +// Viewer includes +#include "llversioninfo.h" #include "llfeaturemanager.h" #include "lluictrlfactory.h" #include "lltexteditor.h" -#include "llalertdialog.h" #include "llerrorcontrol.h" -#include "llviewerimagelist.h" +#include "lleventtimer.h" +#include "llviewertexturelist.h" #include "llgroupmgr.h" #include "llagent.h" +#include "llagentcamera.h" +#include "llagentlanguage.h" #include "llagentwearables.h" #include "llwindow.h" #include "llviewerstats.h" #include "llmd5.h" #include "llpumpio.h" -#include "llimpanel.h" #include "llmimetypes.h" #include "llslurl.h" #include "llstartup.h" @@ -59,32 +53,53 @@ #include "llallocator.h" #include "llares.h" #include "llcurl.h" +#include "lltexturestats.h" +#include "lltexturestats.h" #include "llviewerwindow.h" #include "llviewerdisplay.h" #include "llviewermedia.h" +#include "llviewerparcelmedia.h" +#include "llviewermediafocus.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" #include "llworldmap.h" #include "llmutelist.h" +#include "llviewerhelp.h" #include "lluicolortable.h" #include "llurldispatcher.h" #include "llurlhistory.h" -#include "llfirstuse.h" +//#include "llfirstuse.h" #include "llrender.h" +#include "llteleporthistory.h" #include "lllocationhistory.h" #include "llfasttimerview.h" +#include "llvoicechannel.h" +#include "llvoavatarself.h" +#include "llsidetray.h" +#include "llfeaturemanager.h" +#include "llurlmatch.h" +#include "lltextutil.h" + #include "llweb.h" #include "llsecondlifeurls.h" // Linden library includes +#include "llimagej2c.h" #include "llmemory.h" +#include "llprimitive.h" +#include "llurlaction.h" +#include "llvfile.h" +#include "llvfsthread.h" +#include "llvolumemgr.h" +#include "llxfermanager.h" + +#include "llnotificationmanager.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" // Third party library includes #include <boost/bind.hpp> -#if LL_WINDOWS - #include "llwindebug.h" -#endif #if LL_WINDOWS # include <share.h> // For _SH_DENYWR in initMarkerFile @@ -92,7 +107,10 @@ # include <sys/file.h> // For initMarkerFile support #endif -#include "llnotify.h" +#include "llapr.h" +#include "apr_dso.h" +#include <boost/lexical_cast.hpp> + #include "llviewerkeyboard.h" #include "lllfsthread.h" #include "llworkerthread.h" @@ -109,10 +127,12 @@ #include "llassetstorage.h" #include "llpolymesh.h" #include "llcachename.h" -#include "audioengine.h" +#include "llaudioengine.h" +#include "llstreamingaudio.h" #include "llviewermenu.h" #include "llselectmgr.h" #include "lltrans.h" +#include "lltransutil.h" #include "lltracker.h" #include "llviewerparcelmgr.h" #include "llworldmapview.h" @@ -123,14 +143,14 @@ #include "lldebugview.h" #include "llconsole.h" #include "llcontainerview.h" -#include "llhoverview.h" +#include "lltooltip.h" #include "llsdserialize.h" #include "llworld.h" #include "llhudeffecttrail.h" #include "llvectorperfoptions.h" -#include "llurlsimstring.h" +#include "llslurl.h" #include "llwatchdog.h" // Included so that constants/settings might be initialized @@ -143,17 +163,16 @@ #include "llvotree.h" #include "llvoavatar.h" #include "llfolderview.h" -#include "lltoolbar.h" #include "llagentpilot.h" -#include "llsrv.h" #include "llvovolume.h" #include "llflexibleobject.h" #include "llvosurfacepatch.h" #include "llviewerfloaterreg.h" #include "llcommandlineparser.h" #include "llfloatermemleak.h" +#include "llfloaterreg.h" #include "llfloatersnapshot.h" -#include "llinventoryview.h" +#include "llfloaterinventory.h" // includes for idle() idleShutdown() #include "llviewercontrol.h" @@ -169,6 +188,12 @@ #include "llimview.h" #include "llviewerthrottle.h" #include "llparcel.h" +#include "llavatariconctrl.h" +#include "llgroupiconctrl.h" + +// Include for security api initialization +#include "llsecapi.h" +#include "llmachineid.h" // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either @@ -181,7 +206,19 @@ //---------------------------------------------------------------------------- // llviewernetwork.h #include "llviewernetwork.h" +// define a self-registering event API object +#include "llappviewerlistener.h" +#if (LL_LINUX || LL_SOLARIS) && LL_GTK +#include "glib.h" +#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK + +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // @@ -203,13 +240,9 @@ const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user fl F32 gSimLastTime; // Used in LLAppViewer::init and send_stats() F32 gSimFrames; -BOOL gAllowTapTapHoldRun = TRUE; BOOL gShowObjectUpdates = FALSE; BOOL gUseQuickTime = TRUE; -BOOL gAcceptTOS = FALSE; -BOOL gAcceptCriticalMessage = FALSE; - eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL; LLSD gDebugInfo; @@ -218,8 +251,6 @@ U32 gFrameCount = 0; U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground LLPumpIO* gServicePump = NULL; -BOOL gPacificDaylightTime = FALSE; - U64 gFrameTime = 0; F32 gFrameTimeSeconds = 0.f; F32 gFrameIntervalSeconds = 0.f; @@ -235,14 +266,8 @@ LLTimer gLogoutTimer; static const F32 LOGOUT_REQUEST_TIME = 6.f; // this will be cut short by the LogoutReply msg. F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; -LLUUID gInventoryLibraryOwner; -LLUUID gInventoryLibraryRoot; - BOOL gDisconnected = FALSE; -// Map scale in pixels per region -F32 gMapScale = 128.f; - // used to restore texture state after a mode switch LLFrameTimer gRestoreGLTimer; BOOL gRestoreGL = FALSE; @@ -291,9 +316,10 @@ static std::set<std::string> default_trans_args; void init_default_trans_args() { default_trans_args.insert("SECOND_LIFE"); // World - default_trans_args.insert("SECOND_LIFE_VIEWER"); + default_trans_args.insert("APP_NAME"); + default_trans_args.insert("CAPITALIZED_APP_NAME"); default_trans_args.insert("SECOND_LIFE_GRID"); - default_trans_args.insert("SECOND_LIFE_SUPPORT"); + default_trans_args.insert("SUPPORT_SITE"); } //---------------------------------------------------------------------------- @@ -303,16 +329,12 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x."; static std::string gWindowTitle; -std::string gLoginPage; -std::vector<std::string> gLoginURIs; -static std::string gHelperURI; - LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; void idle_afk_check() { // check idle timers - if (gSavedSettings.getBOOL("AllowIdleAFK") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getF32("AFKTimeout"))) + if (gSavedSettings.getS32("AFKTimeout") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getS32("AFKTimeout"))) { gAgent.setAFK(); } @@ -327,13 +349,52 @@ static void ui_audio_callback(const LLUUID& uuid) } } +bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base) +{ + if(!match || !base || base->getPlainText()) + return false; + + LLUUID match_id = match->getID(); + + LLIconCtrl* icon; + + if(gAgent.isInGroup(match_id, TRUE)) + { + LLGroupIconCtrl::Params icon_params = LLUICtrlFactory::instance().getDefaultParams<LLGroupIconCtrl>(); + icon_params.group_id = match_id; + icon_params.rect = LLRect(0, 16, 16, 0); + icon_params.visible = true; + icon = LLUICtrlFactory::instance().createWidget<LLGroupIconCtrl>(icon_params); + } + else + { + LLAvatarIconCtrl::Params icon_params = LLUICtrlFactory::instance().getDefaultParams<LLAvatarIconCtrl>(); + icon_params.avatar_id = match_id; + icon_params.rect = LLRect(0, 16, 16, 0); + icon_params.visible = true; + icon = LLUICtrlFactory::instance().createWidget<LLAvatarIconCtrl>(icon_params); + } + + LLInlineViewSegment::Params params; + params.force_newline = false; + params.view = icon; + params.left_pad = 4; + params.right_pad = 4; + params.top_pad = -2; + params.bottom_pad = 2; + + base->appendWidget(params," ",false); + + return true; +} + void request_initial_instant_messages() { static BOOL requested = FALSE; if (!requested && gMessageSystem && LLMuteList::getInstance()->isLoaded() - && gAgent.getAvatarObject()) + && isAgentAvatarValid()) { // Auto-accepted inventory items may require the avatar object // to build a correct name. Likewise, inventory offers from @@ -355,14 +416,8 @@ bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue) const S32 NEVER_SUBMIT_REPORT = 2; if(cb == NEVER_SUBMIT_REPORT) { -// LLWatchdog::getInstance()->cleanup(); // SJB: cleaning up a running watchdog thread is unsafe LLAppViewer::instance()->destroyMainloopTimeout(); } - else if(gSavedSettings.getBOOL("WatchdogEnabled") == TRUE) - { - // Don't re-enable the watchdog when we change the setting; this may get called before it's started -// LLWatchdog::getInstance()->init(); - } return true; } @@ -371,7 +426,6 @@ bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue) static void settings_to_globals() { LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad"); - LLBUTTON_V_PAD = gSavedSettings.getS32("ButtonVPad"); BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); @@ -389,11 +443,10 @@ static void settings_to_globals() LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor"); - LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); + LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible"); LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible"); // clamp auto-open time to some minimum usable value LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay")); - LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay"); LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive"); LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections"); LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); @@ -403,10 +456,8 @@ static void settings_to_globals() gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle")); gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); - gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun"); gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); - gMapScale = gSavedSettings.getF32("MapScale"); - LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips"); + LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale"); LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); } @@ -419,7 +470,7 @@ static void settings_modify() LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession; gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); - + gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); #if LL_VECTORIZE if (gSysCPU.hasAltivec()) { @@ -487,35 +538,6 @@ public: } }; -void LLAppViewer::initGridChoice() -{ - // Load up the initial grid choice from: - // - hard coded defaults... - // - command line settings... - // - if dev build, persisted settings... - - // Set the "grid choice", this is specified by command line. - std::string grid_choice = gSavedSettings.getString("CmdLineGridChoice"); - LLViewerLogin::getInstance()->setGridChoice(grid_choice); - - // Load last server choice by default - // ignored if the command line grid choice has been set - if(grid_choice.empty()) - { - S32 server = gSavedSettings.getS32("ServerChoice"); - server = llclamp(server, 0, (S32)GRID_INFO_COUNT - 1); - if(server == GRID_INFO_OTHER) - { - std::string custom_server = gSavedSettings.getString("CustomServer"); - LLViewerLogin::getInstance()->setGridChoice(custom_server); - } - else if(server != (S32)GRID_INFO_NONE) - { - LLViewerLogin::getInstance()->setGridChoice((EGridInfo)server); - } - } -} - //virtual bool LLAppViewer::initSLURLHandler() { @@ -540,7 +562,7 @@ LLAppViewer* LLAppViewer::sInstance = NULL; const std::string LLAppViewer::sGlobalSettingsName = "Global"; LLTextureCache* LLAppViewer::sTextureCache = NULL; -LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL; +LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLAppViewer::LLAppViewer() : @@ -558,9 +580,9 @@ LLAppViewer::LLAppViewer() : mYieldTime(-1), mMainloopTimeout(NULL), mAgentRegionLastAlive(false), - mFastTimerLogThread(NULL), mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)), - mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)) + mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)), + mFastTimerLogThread(NULL) { if(NULL != sInstance) { @@ -588,7 +610,8 @@ bool LLAppViewer::init() // into the log files during normal startup until AFTER // we run the "program crashed last time" error handler below. // - + LLFastTimer::reset(); + // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API gDirUtilp->initAppDirs("SecondLife"); @@ -606,24 +629,38 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; - + + // write Google Breakpad minidump files to our log directory + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + setMiniDumpDir(logdir); + + // Although initLogging() is the right place to mess with + // setFatalFunction(), we can't query gSavedSettings until after + // initConfiguration(). + S32 rc(gSavedSettings.getS32("QAModeTermCode")); + if (rc >= 0) + { + // QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit() + // rather than exit() because normal cleanup depends too much on + // successful startup! + LLError::setFatalFunction(boost::bind(_exit, rc)); + } + mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. LLCurl::initClass(); + LLMachineID::init(); initThreads(); - writeSystemInfo(); // Build a string representing the current version number. - gCurrentVersion = llformat("%s %d.%d.%d.%d", - gSavedSettings.getString("VersionChannelName").c_str(), - LL_VERSION_MAJOR, - LL_VERSION_MINOR, - LL_VERSION_PATCH, - LL_VERSION_BUILD ); + gCurrentVersion = llformat("%s %s", + gSavedSettings.getString("VersionChannelName").c_str(), + LLVersionInfo::getVersion().c_str()); ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -631,6 +668,9 @@ bool LLAppViewer::init() ////////////////////////////////////////////////////////////////////////////// // *FIX: The following code isn't grouped into functions yet. + // Statistics / debug timer initialization + init_statistics(); + // // Various introspection concerning the libs we're using - particularly // the libs involved in getting to a full login screen. @@ -641,6 +681,11 @@ bool LLAppViewer::init() // Get the single value from the crash settings file, if it exists std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); gCrashSettings.loadFromFile(crash_settings_filename); + if(gSavedSettings.getBOOL("IgnoreAllNotifications")) + { + gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND); + gCrashSettings.saveToFile(crash_settings_filename, FALSE); + } ///////////////////////////////////////////////// // OS-specific login dialogs @@ -653,8 +698,6 @@ bool LLAppViewer::init() mNumSessions++; gSavedSettings.setS32("NumSessions", mNumSessions); - gSavedSettings.setString("HelpLastVisitedURL",gSavedSettings.getString("HelpHomeURL")); - if (gSavedSettings.getBOOL("VerboseLogs")) { LLError::setPrintLocation(true); @@ -663,26 +706,36 @@ bool LLAppViewer::init() // Widget construction depends on LLUI being initialized LLUI::settings_map_t settings_map; settings_map["config"] = &gSavedSettings; - settings_map["color"] = &gSavedSkinSettings; settings_map["ignores"] = &gWarningSettings; settings_map["floater"] = &gSavedSettings; // *TODO: New settings file settings_map["account"] = &gSavedPerAccountSettings; LLUI::initClass(settings_map, - LLUIImageList::getInstance(), - ui_audio_callback, - &LLUI::sGLScaleFactor); + LLUIImageList::getInstance(), + ui_audio_callback, + &LLUI::sGLScaleFactor); // Setup paths and LLTrans after LLUI::initClass has been called LLUI::setupPaths(); - LLTrans::parseStrings("strings.xml", default_trans_args); + LLTransUtil::parseStrings("strings.xml", default_trans_args); + LLTransUtil::parseLanguageStrings("language_settings.xml"); + + // LLKeyboard relies on LLUI to know what some accelerator keys are called. + LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); LLWeb::initClass(); // do this after LLUI - - LLTextEditor::setURLCallbacks(&LLWeb::loadURL, - &LLURLDispatcher::dispatchFromTextEditor, - &LLURLDispatcher::dispatchFromTextEditor); + // Provide the text fields with callbacks for opening Urls + LLUrlAction::setOpenURLCallback(&LLWeb::loadURL); + LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal); + LLUrlAction::setOpenURLExternalCallback(&LLWeb::loadURLExternal); + LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor); + + // Let code in llui access the viewer help floater + LLUI::sHelpImpl = LLViewerHelp::getInstance(); + + // Load translations for tooltips + LLFloater::initClass(); ///////////////////////////////////////////////// @@ -702,7 +755,15 @@ bool LLAppViewer::init() LLViewerJointMesh::updateVectorize(); // load MIME type -> media impl mappings - LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") ); + std::string mime_types_name; +#if LL_DARWIN + mime_types_name = "mime_types_mac.xml"; +#elif LL_LINUX + mime_types_name = "mime_types_linux.xml"; +#else + mime_types_name = "mime_types.xml"; +#endif + LLMIMETypes::parseMIMETypes( mime_types_name ); // Copy settings to globals. *TODO: Remove or move to appropriage class initializers settings_to_globals(); @@ -723,10 +784,6 @@ bool LLAppViewer::init() return false; } - // Always fetch the Ethernet MAC address, needed both for login - // and password load. - LLUUID::getNodeID(gMACAddress); - // Prepare for out-of-memory situations, during which we will crash on // purpose and save a dump. #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP @@ -750,18 +807,12 @@ bool LLAppViewer::init() // // Initialize the window // + gGLActive = TRUE; initWindow(); // call all self-registered classes LLInitClassList::instance().fireCallbacks(); - #if LL_LCD_COMPILE - // start up an LCD window on a logitech keyboard, if there is one - HINSTANCE hInstance = GetModuleHandle(NULL); - gLcdScreen = new LLLCD(hInstance); - CreateLCDDebugWindows(); -#endif - LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts gGLManager.getGLInfo(gDebugInfo); @@ -814,7 +865,7 @@ bool LLAppViewer::init() minSpecs += "\n"; unsupported = true; } - if(gSysCPU.getMhz() < minCPU) + if(gSysCPU.getMHz() < minCPU) { minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU"); minSpecs += "\n"; @@ -829,7 +880,7 @@ bool LLAppViewer::init() if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN) { - LLNotifications::instance().add("UnknownGPU"); + LLNotificationsUtil::add("UnknownGPU"); } if(unsupported) @@ -838,12 +889,13 @@ bool LLAppViewer::init() || gSavedSettings.getBOOL("WarnUnsupportedHardware")) { args["MINSPECS"] = minSpecs; - LLNotifications::instance().add("UnsupportedHardware", args ); + LLNotificationsUtil::add("UnsupportedHardware", args ); } } } + // save the graphics card gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString(); @@ -855,14 +907,65 @@ bool LLAppViewer::init() LLViewerJoystick::getInstance()->init(false); + try { + initializeSecHandler(); + } + catch (LLProtectedDataException ex) + { + LLNotificationsUtil::add("CorruptedProtectedDataStore"); + } + LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback); + + + gGLActive = FALSE; + if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0) + { + loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort")); + } + + LLViewerMedia::initClass(); + LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; + + //EXT-7013 - On windows for some locale (Japanese) standard + //datetime formatting functions didn't support some parameters such as "weekday". + //Names for days and months localized in xml are also useful for Polish locale(STORM-107). + std::string language = LLControlGroup::getInstance(sGlobalSettingsName)->getString("Language"); + if(language == "ja" || language == "pl") + { + LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); + LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); + LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); + LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); + LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); + + LLStringOps::sAM = LLTrans::getString("dateTimeAM"); + LLStringOps::sPM = LLTrans::getString("dateTimePM"); + } + + LLAgentLanguage::init(); + return true; } +static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages"); +static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep"); +static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache"); +static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode"); +static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread"); +static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread"); +static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads"); +static LLFastTimer::DeclareTimer FTM_IDLE("Idle"); +static LLFastTimer::DeclareTimer FTM_PUMP("Pump"); +static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares"); +static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service"); +static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback"); +static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot"); +static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update"); + bool LLAppViewer::mainLoop() { LLMemType mt1(LLMemType::MTYPE_MAIN); mMainloopTimeout = new LLWatchdogTimeout(); - // *FIX:Mani - Make this a setting, once new settings exist in this branch. //------------------------------------------- // Run main loop until time to quit @@ -872,12 +975,11 @@ bool LLAppViewer::mainLoop() gServicePump = new LLPumpIO(gAPRPoolp); LLHTTPClient::setPump(*gServicePump); LLCurl::setCAFile(gDirUtilp->getCAFile()); - + // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. LLVoiceChannel::initClass(); - LLVoiceClient::init(gServicePump); - + LLVoiceClient::getInstance()->init(gServicePump); LLTimer frameTimer,idleTimer; LLTimer debugTime; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); @@ -894,21 +996,22 @@ bool LLAppViewer::mainLoop() while (!LLApp::isExiting()) { LLFastTimer::nextFrame(); // Should be outside of any timer instances + try { pingMainloopTimeout("Main:MiscNativeWindowEvents"); if (gViewerWindow) { - LLFastTimer t2(LLFastTimer::FTM_MESSAGES); + LLFastTimer t2(FTM_MESSAGES); gViewerWindow->mWindow->processMiscNativeEvents(); } - + pingMainloopTimeout("Main:GatherInput"); if (gViewerWindow) { - LLFastTimer t2(LLFastTimer::FTM_MESSAGES); + LLFastTimer t2(FTM_MESSAGES); if (!restoreErrorTrap()) { llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl; @@ -926,9 +1029,11 @@ bool LLAppViewer::mainLoop() #endif //memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->idle() ; + mem_leak_instance->idle() ; } // canonical per-frame event @@ -957,18 +1062,28 @@ bool LLAppViewer::mainLoop() { pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! - LLFastTimer t3(LLFastTimer::FTM_IDLE); + LLFastTimer t3(FTM_IDLE); idle(); if (gAres != NULL && gAres->isInitialized()) { LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP); pingMainloopTimeout("Main:ServicePump"); - LLFastTimer t4(LLFastTimer::FTM_PUMP); - gAres->process(); - // this pump is necessary to make the login screen show up - gServicePump->pump(); - gServicePump->callback(); + LLFastTimer t4(FTM_PUMP); + { + LLFastTimer t(FTM_PUMP_ARES); + gAres->process(); + } + { + LLFastTimer t(FTM_PUMP_SERVICE); + // this pump is necessary to make the login screen show up + gServicePump->pump(); + + { + LLFastTimer t(FTM_SERVICE_CALLBACK); + gServicePump->callback(); + } + } } resumeMainloopTimeout(); @@ -986,10 +1101,11 @@ bool LLAppViewer::mainLoop() if (!LLApp::isExiting()) { pingMainloopTimeout("Main:Display"); + gGLActive = TRUE; display(); - pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots + gGLActive = FALSE; } } @@ -1001,9 +1117,8 @@ bool LLAppViewer::mainLoop() // Sleep and run background threads { LLMemType mt_sleep(LLMemType::MTYPE_SLEEP); - LLFastTimer t2(LLFastTimer::FTM_SLEEP); - bool run_multiple_threads = gSavedSettings.getBOOL("RunMultipleThreads"); - + LLFastTimer t2(FTM_SLEEP); + // yield some time to the os based on command line option if(mYieldTime >= 0) { @@ -1040,34 +1155,64 @@ bool LLAppViewer::mainLoop() ms_sleep(500); } - - const F64 min_frame_time = 0.0; //(.0333 - .0010); // max video frame rate = 30 fps - const F64 min_idle_time = 0.0; //(.0010); // min idle time = 1 ms - const F64 max_idle_time = run_multiple_threads ? min_idle_time : llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second + static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds + const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second idleTimer.reset(); - while(1) + bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ; + S32 total_work_pending = 0; + S32 total_io_pending = 0; + while(!is_slow)//do not unpause threads if the frame rates are very low. { S32 work_pending = 0; S32 io_pending = 0; - work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread - work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread - work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread - io_pending += LLVFSThread::updateClass(1); - io_pending += LLLFSThread::updateClass(1); + { + LLFastTimer ftm(FTM_TEXTURE_CACHE); + work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread + } + { + LLFastTimer ftm(FTM_DECODE); + work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread + } + { + LLFastTimer ftm(FTM_DECODE); + work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread + } + + { + LLFastTimer ftm(FTM_VFS); + io_pending += LLVFSThread::updateClass(1); + } + { + LLFastTimer ftm(FTM_LFS); + io_pending += LLLFSThread::updateClass(1); + } + if (io_pending > 1000) { ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up } - F64 frame_time = frameTimer.getElapsedTimeF64(); - F64 idle_time = idleTimer.getElapsedTimeF64(); - if (frame_time >= min_frame_time && - idle_time >= min_idle_time && - (!work_pending || idle_time >= max_idle_time)) + total_work_pending += work_pending ; + total_io_pending += io_pending ; + + if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time) { break; } } + + if(!total_work_pending) //pause texture fetching threads if nothing to process. + { + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); + LLAppViewer::getTextureFetch()->pause(); + } + if(!total_io_pending) //pause file threads if nothing to process. + { + LLVFSThread::sLocal->pause(); + LLLFSThread::sLocal->pause(); + } + if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) { @@ -1075,17 +1220,6 @@ bool LLAppViewer::mainLoop() } frameTimer.reset(); - // Prevent the worker threads from running while rendering. - // if (LLThread::processorCount()==1) //pause() should only be required when on a single processor client... - if (run_multiple_threads == FALSE) - { - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); - // LLAppViewer::getTextureFetch()->pause(); // Don't pause the fetch (IO) thread - } - //LLVFSThread::sLocal->pause(); // Prevent the VFS thread from running while rendering. - //LLLFSThread::sLocal->pause(); // Prevent the LFS thread from running while rendering. - resumeMainloopTimeout(); pingMainloopTimeout("Main:End"); @@ -1095,9 +1229,11 @@ bool LLAppViewer::mainLoop() catch(std::bad_alloc) { //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->stop() ; + mem_leak_instance->stop() ; llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ; } else @@ -1122,9 +1258,11 @@ bool LLAppViewer::mainLoop() llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ; //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->stop() ; + mem_leak_instance->stop() ; } } } @@ -1140,6 +1278,29 @@ bool LLAppViewer::mainLoop() bool LLAppViewer::cleanup() { + // workaround for DEV-35406 crash on shutdown + LLEventPumps::instance().reset(); + + // remove any old breakpad minidump files from the log directory + if (! isError()) + { + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + } + + // *TODO - generalize this and move DSO wrangling to a helper class -brad + std::set<struct apr_dso_handle_t *>::const_iterator i; + for(i = mPlugins.begin(); i != mPlugins.end(); ++i) + { + int (*ll_plugin_stop_func)(void) = NULL; + apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop"); + ll_plugin_stop_func(); + + rv = apr_dso_unload(*i); + } + mPlugins.clear(); + //---------------------------------------------- //this test code will be removed after the test //test manual call stack tracer @@ -1154,7 +1315,7 @@ bool LLAppViewer::cleanup() // to ensure shutdown order LLMortician::setZealous(TRUE); - LLVoiceClient::terminate(); + LLVoiceClient::getInstance()->terminate(); disconnectViewer(); @@ -1204,6 +1365,14 @@ bool LLAppViewer::cleanup() if (gAudiop) { + // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. + + LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl(); + delete sai; + gAudiop->setStreamingAudioImpl(NULL); + + // shut down the audio subsystem + bool want_longname = false; if (gAudiop->getDriverName(want_longname) == "FMOD") { @@ -1241,9 +1410,6 @@ bool LLAppViewer::cleanup() llinfos << "Cache files removed" << llendflush; - - cleanup_menus(); - // Wait for any pending VFS IO while (1) { @@ -1256,15 +1422,25 @@ bool LLAppViewer::cleanup() llinfos << "Waiting for pending IO to finish: " << pending << llendflush; ms_sleep(100); } - llinfos << "Shutting down." << llendflush; + llinfos << "Shutting down Views" << llendflush; // Destroy the UI if( gViewerWindow) gViewerWindow->shutdownViews(); + llinfos << "Cleaning up Inventory" << llendflush; + + // Cleanup Inventory after the UI since it will delete any remaining observers + // (Deleted observers should have already removed themselves) + gInventory.cleanupInventory(); + + llinfos << "Cleaning up Selections" << llendflush; + // Clean up selection managers after UI is destroyed, as UI may be observing them. // Clean up before GL is shut down because we might be holding on to objects with texture references LLSelectMgr::cleanupGlobals(); + + llinfos << "Shutting down OpenGL" << llendflush; // Shut down OpenGL if( gViewerWindow) @@ -1278,11 +1454,18 @@ bool LLAppViewer::cleanup() gViewerWindow = NULL; llinfos << "ViewerWindow deleted" << llendflush; } + + llinfos << "Cleaning up Keyboard & Joystick" << llendflush; // viewer UI relies on keyboard so keep it aound until viewer UI isa gone delete gKeyboard; gKeyboard = NULL; + // Turn off Space Navigator and similar devices + LLViewerJoystick::getInstance()->terminate(); + + llinfos << "Cleaning up Objects" << llendflush; + LLViewerObject::cleanupVOClasses(); LLWaterParamManager::cleanupClass(); @@ -1305,6 +1488,8 @@ bool LLAppViewer::cleanup() } LLPrimitive::cleanupVolumeManager(); + llinfos << "Additional Cleanup..." << llendflush; + LLViewerParcelMgr::cleanupGlobals(); // *Note: this is where gViewerStats used to be deleted. @@ -1324,15 +1509,10 @@ bool LLAppViewer::cleanup() // Also after shutting down the messaging system since it has VFS dependencies // + llinfos << "Cleaning up VFS" << llendflush; LLVFile::cleanupClass(); - llinfos << "VFS cleaned up" << llendflush; - // Quitting with "Remember Password" turned off should always stomp your - // saved password, whether or not you successfully logged in. JC - if (!gSavedSettings.getBOOL("RememberPassword")) - { - LLStartUp::deletePasswordFromDisk(); - } + llinfos << "Saving Data" << llendflush; // Store the time of our current logoff gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); @@ -1341,12 +1521,19 @@ bool LLAppViewer::cleanup() // save their rects on delete. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - //*FIX: don't overwrite user color tweaks with *all* colors - gSavedSkinSettings.saveToFile(gSavedSettings.getString("SkinningSettingsFile"), TRUE); - // PerAccountSettingsFile should be empty if no use has been logged on. + LLUIColorTable::instance().saveUserSettings(); + + // PerAccountSettingsFile should be empty if no user has been logged on. // *FIX:Mani This should get really saved in a "logoff" mode. - gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); - llinfos << "Saved settings" << llendflush; + if (gSavedSettings.getString("PerAccountSettingsFile").empty()) + { + llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; + } + else + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + llinfos << "Saved settings" << llendflush; + } std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults @@ -1355,10 +1542,6 @@ bool LLAppViewer::cleanup() std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings")); gWarningSettings.saveToFile(warnings_settings_filename, TRUE); - gSavedSettings.cleanup(); - gSavedSkinSettings.cleanup(); - gCrashSettings.cleanup(); - // Save URL history file LLURLHistory::saveFile("url_history.xml"); @@ -1376,6 +1559,17 @@ bool LLAppViewer::cleanup() writeDebugInfo(); + LLLocationHistory::getInstance()->save(); + + LLAvatarIconIDCache::getInstance()->save(); + + LLViewerMedia::saveCookieFile(); + + // Stop the plugin read thread if it's running. + LLPluginProcessParent::setUseReadThread(false); + + llinfos << "Shutting down Threads" << llendflush; + // Let threads finish LLTimer idleTimer; idleTimer.reset(); @@ -1389,30 +1583,35 @@ bool LLAppViewer::cleanup() pending += LLVFSThread::updateClass(0); pending += LLLFSThread::updateClass(0); F64 idle_time = idleTimer.getElapsedTimeF64(); - if (!pending || idle_time >= max_idle_time) + if(!pending) + { + break ; //done + } + else if(idle_time >= max_idle_time) { llwarns << "Quitting with pending background tasks." << llendl; break; } } - + // Delete workers first // shotdown all worker threads before deleting them in case of co-dependencies sTextureCache->shutdown(); sTextureFetch->shutdown(); sImageDecodeThread->shutdown(); + sTextureFetch->shutDownTextureCacheThread() ; + sTextureFetch->shutDownImageDecodeThread() ; + delete sTextureCache; sTextureCache = NULL; delete sTextureFetch; sTextureFetch = NULL; delete sImageDecodeThread; sImageDecodeThread = NULL; - - LLLocationHistory::getInstance()->save(); delete mFastTimerLogThread; mFastTimerLogThread = NULL; - + if (LLFastTimerView::sAnalyzePerformance) { llinfos << "Analyzing performance" << llendl; @@ -1434,11 +1633,14 @@ bool LLAppViewer::cleanup() } LLMetricPerformanceTester::cleanClass() ; + llinfos << "Cleaning up Media and Textures" << llendflush; + //Note: - //LLViewerMedia::cleanupClass() has to be put before gImageList.shutdown() + //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao LLViewerMedia::cleanupClass(); - gImageList.shutdown(); // shutdown again in case a callback added something + LLViewerParcelMedia::cleanupClass(); + gTextureList.shutdown(); // shutdown again in case a callback added something LLUIImageList::getInstance()->cleanUp(); // This should eventually be done in LLAppViewer @@ -1446,28 +1648,31 @@ bool LLAppViewer::cleanup() LLVFSThread::cleanupClass(); LLLFSThread::cleanupClass(); - llinfos << "VFS Thread finished" << llendflush; - #ifndef LL_RELEASE_FOR_DOWNLOAD llinfos << "Auditing VFS" << llendl; gVFS->audit(); #endif + llinfos << "Misc Cleanup" << llendflush; + // For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up. // (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve delete gStaticVFS; gStaticVFS = NULL; delete gVFS; gVFS = NULL; + + gSavedSettings.cleanup(); + LLUIColorTable::instance().clear(); + gCrashSettings.cleanup(); LLWatchdog::getInstance()->cleanup(); + llinfos << "Shutting down message system" << llendflush; end_messaging_system(); - llinfos << "Message system deleted." << llendflush; // *NOTE:Mani - The following call is not thread safe. LLCurl::cleanupClass(); - llinfos << "LLCurl cleaned up." << llendflush; // If we're exiting to launch an URL, do that here so the screen // is at the right resolution before we launch IE. @@ -1482,13 +1687,13 @@ bool LLAppViewer::cleanup() // HACK: Attempt to wait until the screen res. switch is complete. ms_sleep(1000); - LLWeb::loadURLExternal( gLaunchFileOnQuit ); + LLWeb::loadURLExternal( gLaunchFileOnQuit, false ); llinfos << "File launched." << llendflush; } ll_close_fail_log(); - llinfos << "Goodbye" << llendflush; + llinfos << "Goodbye!" << llendflush; // return 0; return true; @@ -1521,22 +1726,14 @@ bool LLAppViewer::initThreads() static const bool enable_threads = true; #endif - const S32 NEVER_SUBMIT_REPORT = 2; - bool use_watchdog = gSavedSettings.getBOOL("WatchdogEnabled"); - bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT; - if(use_watchdog && send_reports) - { - LLWatchdog::getInstance()->init(watchdog_killer_callback); - } - - LLVFSThread::initClass(enable_threads && true); - LLLFSThread::initClass(enable_threads && true); + LLVFSThread::initClass(enable_threads && false); + LLLFSThread::initClass(enable_threads && false); // Image decoding - LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true); + LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); - LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false); - LLImage::initClass(LLAppViewer::getImageDecodeThread()); + LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true); + LLImage::initClass(); if (LLFastTimer::sLog || LLFastTimer::sMetricLog) { @@ -1569,7 +1766,7 @@ bool LLAppViewer::initLogging() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")); LLError::setFatalFunction(errorCallback); - + // Remove the last ".old" log file. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.old"); @@ -1664,7 +1861,7 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, } else { - llwarns << "Cannot load " << full_settings_path << " - No settings found." << llendl; + llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl; } } else @@ -1696,43 +1893,7 @@ std::string LLAppViewer::getSettingsFilename(const std::string& location_key, void LLAppViewer::loadColorSettings() { - gSavedSkinSettings.cleanup(); - - loadSettingsFromDirectory("DefaultSkin"); - loadSettingsFromDirectory("CurrentSkin", true); - loadSettingsFromDirectory("UserSkin"); - - class ColorConverterFunctor : public LLControlGroup::ApplyFunctor - { - public: - explicit ColorConverterFunctor(LLUIColorTable::Params& result) - :mResult(result) - { - } - - void apply(const std::string& name, LLControlVariable* control) - { - if(control->isType(TYPE_COL4)) - { - LLUIColorTable::ColorParams color; - color.value = control->getValue(); - - LLUIColorTable::ColorEntryParams color_entry; - color_entry.name = name; - color_entry.color = color; - - mResult.color_entries.add(color_entry); - } - } - - private: - LLUIColorTable::Params& mResult; - }; - - LLUIColorTable::Params params; - ColorConverterFunctor ccf(params); - LLControlGroup::getInstance("Skinning")->applyToAll(&ccf); - LLUIColorTable::instance().init(params); + LLUIColorTable::instance().loadFromSettings(); } bool LLAppViewer::initConfiguration() @@ -1769,65 +1930,64 @@ bool LLAppViewer::initConfiguration() } LLUI::setupPaths(); // setup paths for LLTrans based on settings files only - LLTrans::parseStrings("strings.xml", default_trans_args); - + LLTransUtil::parseStrings("strings.xml", default_trans_args); + LLTransUtil::parseLanguageStrings("language_settings.xml"); // - set procedural settings // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet gSavedSettings.setString("ClientSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); - gSavedSettings.setString("SkinningSettingsFile", - gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("UserSkin", "Skinning"))); - - gSavedSettings.setString("VersionChannelName", LL_CHANNEL); + gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel()); #ifndef LL_RELEASE_FOR_DOWNLOAD - gSavedSettings.setBOOL("ShowConsoleWindow", TRUE); - gSavedSettings.setBOOL("AllowMultipleViewers", TRUE); + // provide developer build only overrides for these control variables that are not + // persisted to settings.xml + LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow"); + if (c) + { + c->setValue(true, false); + } + c = gSavedSettings.getControl("AllowMultipleViewers"); + if (c) + { + c->setValue(true, false); + } #endif - //*FIX:Mani - Set default to disabling watchdog mainloop - // timeout for mac and linux. There is no call stack info - // on these platform to help debug. #ifndef LL_RELEASE_FOR_DOWNLOAD - gSavedSettings.setBOOL("WatchdogEnabled", FALSE); gSavedSettings.setBOOL("QAMode", TRUE ); + gSavedSettings.setS32("WatchdogEnabled", 0); #endif - -#ifndef LL_WINDOWS - gSavedSettings.setBOOL("WatchdogEnabled", FALSE); -#endif - + gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2)); // These are warnings that appear on the first experience of that condition. // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse // for disable/reset ability - LLFirstUse::addConfigVariable("FirstBalanceIncrease"); - LLFirstUse::addConfigVariable("FirstBalanceDecrease"); - LLFirstUse::addConfigVariable("FirstSit"); - LLFirstUse::addConfigVariable("FirstMap"); - LLFirstUse::addConfigVariable("FirstGoTo"); - LLFirstUse::addConfigVariable("FirstBuild"); - LLFirstUse::addConfigVariable("FirstLeftClickNoHit"); - LLFirstUse::addConfigVariable("FirstTeleport"); - LLFirstUse::addConfigVariable("FirstOverrideKeys"); - LLFirstUse::addConfigVariable("FirstAttach"); - LLFirstUse::addConfigVariable("FirstAppearance"); - LLFirstUse::addConfigVariable("FirstInventory"); - LLFirstUse::addConfigVariable("FirstSandbox"); - LLFirstUse::addConfigVariable("FirstFlexible"); - LLFirstUse::addConfigVariable("FirstDebugMenus"); - LLFirstUse::addConfigVariable("FirstStreamingMusic"); - LLFirstUse::addConfigVariable("FirstStreamingVideo"); - LLFirstUse::addConfigVariable("FirstSculptedPrim"); - LLFirstUse::addConfigVariable("FirstVoice"); - LLFirstUse::addConfigVariable("FirstMedia"); +// LLFirstUse::addConfigVariable("FirstBalanceIncrease"); +// LLFirstUse::addConfigVariable("FirstBalanceDecrease"); +// LLFirstUse::addConfigVariable("FirstSit"); +// LLFirstUse::addConfigVariable("FirstMap"); +// LLFirstUse::addConfigVariable("FirstGoTo"); +// LLFirstUse::addConfigVariable("FirstBuild"); +// LLFirstUse::addConfigVariable("FirstLeftClickNoHit"); +// LLFirstUse::addConfigVariable("FirstTeleport"); +// LLFirstUse::addConfigVariable("FirstOverrideKeys"); +// LLFirstUse::addConfigVariable("FirstAttach"); +// LLFirstUse::addConfigVariable("FirstAppearance"); +// LLFirstUse::addConfigVariable("FirstInventory"); +// LLFirstUse::addConfigVariable("FirstSandbox"); +// LLFirstUse::addConfigVariable("FirstFlexible"); +// LLFirstUse::addConfigVariable("FirstDebugMenus"); +// LLFirstUse::addConfigVariable("FirstSculptedPrim"); +// LLFirstUse::addConfigVariable("FirstVoice"); +// LLFirstUse::addConfigVariable("FirstMedia"); // - read command line settings. LLControlGroupCLP clp; std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "cmd_line.xml"); + clp.configure(cmd_line_config, &gSavedSettings); if(!initParseCommandLine(clp)) @@ -1910,7 +2070,6 @@ bool LLAppViewer::initConfiguration() } } - 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")) @@ -1971,6 +2130,11 @@ bool LLAppViewer::initConfiguration() { LLAgentPilot::sReplaySession = TRUE; } + + if (clp.hasOption("nonotifications")) + { + gSavedSettings.setBOOL("IgnoreAllNotifications", TRUE); + } if (clp.hasOption("debugsession")) { @@ -1999,39 +2163,25 @@ bool LLAppViewer::initConfiguration() // injection and steal passwords. Phoenix. SL-55321 if(clp.hasOption("url")) { - std::string slurl = clp.getOption("url")[0]; - if (LLSLURL::isSLURLCommand(slurl)) - { - LLStartUp::sSLURLCommand = slurl; - } - else - { - LLURLSimString::setString(slurl); - } + LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0])); + if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION) + { + LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid()); + + } } else if(clp.hasOption("slurl")) { - std::string slurl = clp.getOption("slurl")[0]; - if(LLSLURL::isSLURL(slurl)) - { - if (LLSLURL::isSLURLCommand(slurl)) - { - LLStartUp::sSLURLCommand = slurl; - } - else - { - LLURLSimString::setString(slurl); - } - } + LLSLURL start_slurl(clp.getOption("slurl")[0]); + LLStartUp::setStartSLURL(start_slurl); } const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) { - gDirUtilp->setSkinFolder(skinfolder->getValue().asString()); - - gSavedSettings.setString("SkinningSettingsFile", - gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("UserSkin", "Skinning"))); + // hack to force the skin to default. + //gDirUtilp->setSkinFolder(skinfolder->getValue().asString()); + gDirUtilp->setSkinFolder("default"); } mYieldTime = gSavedSettings.getS32("YieldTime"); @@ -2051,7 +2201,7 @@ bool LLAppViewer::initConfiguration() #if LL_DARWIN // Initialize apple menubar and various callbacks - init_apple_menu(LLTrans::getString("SECOND_LIFE_VIEWER").c_str()); + init_apple_menu(LLTrans::getString("APP_NAME").c_str()); #if __ppc__ // If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further. @@ -2073,10 +2223,12 @@ bool LLAppViewer::initConfiguration() // Display splash screen. Must be after above check for previous // crash as this dialog is always frontmost. - std::ostringstream splash_msg; - splash_msg << "Loading " << LLTrans::getString("SECOND_LIFE") << "..."; + std::string splash_msg; + LLStringUtil::format_map_t args; + args["[APP_NAME]"] = LLTrans::getString("SECOND_LIFE"); + splash_msg = LLTrans::getString("StartupLoading", args); LLSplashScreen::show(); - LLSplashScreen::update(splash_msg.str()); + LLSplashScreen::update(splash_msg); //LLVolumeMgr::initClass(); LLVolumeMgr* volume_manager = new LLVolumeMgr(); @@ -2090,7 +2242,7 @@ bool LLAppViewer::initConfiguration() // // Set the name of the window // - gWindowTitle = LLTrans::getString("SECOND_LIFE_VIEWER"); + gWindowTitle = LLTrans::getString("APP_NAME"); #if LL_DEBUG gWindowTitle += std::string(" [DEBUG] ") + gArgs; #else @@ -2102,18 +2254,10 @@ bool LLAppViewer::initConfiguration() // don't call anotherInstanceRunning() when doing URL handoff, as // it relies on checking a marker file which will not work when running // out of different directories - std::string slurl; - if (!LLStartUp::sSLURLCommand.empty()) - { - slurl = LLStartUp::sSLURLCommand; - } - else if (LLURLSimString::parse()) - { - slurl = LLURLSimString::getURL(); - } - if (!slurl.empty()) + + if (LLStartUp::getStartSLURL().isValid()) { - if (sendURLToOtherInstance(slurl)) + if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString())) { // successfully handed off URL to existing instance, exit return false; @@ -2169,9 +2313,9 @@ bool LLAppViewer::initConfiguration() // need to do this here - need to have initialized global settings first std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" ); - if ( nextLoginLocation.length() ) + if ( !nextLoginLocation.empty() ) { - LLURLSimString::setString( nextLoginLocation ); + LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation)); }; gLastRunVersion = gSavedSettings.getString("LastRunVersion"); @@ -2186,17 +2330,7 @@ void LLAppViewer::checkForCrash(void) { #if LL_SEND_CRASH_REPORTS - //*NOTE:Mani The current state of the crash handler has the MacOSX - // sending all crash reports as freezes, in order to let - // the MacOSX CrashRepoter generate stacks before spawning the - // SL crash logger. - // The Linux and Windows clients generate their own stacks and - // spawn the SL crash logger immediately. This may change in the future. -#if LL_DARWIN - if(gLastExecEvent != LAST_EXEC_NORMAL) -#else if (gLastExecEvent == LAST_EXEC_FROZE) -#endif { llinfos << "Last execution froze, requesting to send crash report." << llendl; // @@ -2207,7 +2341,7 @@ void LLAppViewer::checkForCrash(void) { std::ostringstream msg; msg << LLTrans::getString("MBFrozenCrashed"); - std::string alert = LLTrans::getString("SECOND_LIFE_VIEWER") + " " + LLTrans::getString("MBAlert"); + std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert"); choice = OSMessageBox(msg.str(), alert, OSMB_YESNO); @@ -2244,9 +2378,6 @@ bool LLAppViewer::initWindow() // store setting in a global for easy access and modification gNoRender = gSavedSettings.getBOOL("DisableRendering"); - // Hide the splash screen - LLSplashScreen::hide(); - // always start windowed BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth"); gViewerWindow = new LLViewerWindow(gWindowTitle, @@ -2254,17 +2385,31 @@ bool LLAppViewer::initWindow() gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"), gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"), FALSE, ignorePixelDepth); - - if (!gSavedSettings.getBOOL("NotFullScreen")) + + // Need to load feature table before cheking to start watchdog. + const S32 NEVER_SUBMIT_REPORT = 2; + bool use_watchdog = false; + int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); + if(watchdog_enabled_setting == -1){ + use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); + } + else { - gViewerWindow->toggleFullscreen(FALSE); - // request to go full screen... which will be delayed until login + // The user has explicitly set this setting; always use that value. + use_watchdog = bool(watchdog_enabled_setting); } - + + bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT; + if(use_watchdog && send_reports) + { + LLWatchdog::getInstance()->init(watchdog_killer_callback); + } + + LLNotificationsUI::LLNotificationManager::getInstance(); + if (gSavedSettings.getBOOL("WindowMaximized")) { gViewerWindow->mWindow->maximize(); - gViewerWindow->getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio")); } if (!gNoRender) @@ -2324,17 +2469,10 @@ void LLAppViewer::cleanupSavedSettings() { gSavedSettings.setBOOL("MouseSun", FALSE); - gSavedSettings.setBOOL("FlyBtnState", FALSE); - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc); - gSavedSettings.setBOOL("AllowTapTapHoldRun", gAllowTapTapHoldRun); gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates); if (!gNoRender) @@ -2345,11 +2483,10 @@ void LLAppViewer::cleanupSavedSettings() } } - // save window position if not fullscreen + // save window position if not maximized // as we don't track it in callbacks - BOOL fullscreen = gViewerWindow->mWindow->getFullscreen(); BOOL maximized = gViewerWindow->mWindow->getMaximized(); - if (!fullscreen && !maximized) + if (!maximized) { LLCoordScreen window_pos; @@ -2360,13 +2497,12 @@ void LLAppViewer::cleanupSavedSettings() } } - gSavedSettings.setF32("MapScale", gMapScale ); - gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips); + gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale ); // Some things are cached in LLAgent. - if (gAgent.mInitialized) + if (gAgent.isInitialized()) { - gSavedSettings.setF32("RenderFarClip", gAgent.mDrawDistance); + gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance); } } @@ -2381,16 +2517,16 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["SLLog"] = LLError::logFileName(); gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); - gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR; - gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR; - gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH; - gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD; + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild(); gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily(); - gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMhz(); + gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz(); gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec(); gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); @@ -2401,9 +2537,9 @@ void LLAppViewer::writeSystemInfo() // The user is not logged on yet, but record the current grid choice login url // which may have been the intended grid. This can b - gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); + gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel(); - // *FIX:Mani - move this ddown in llappviewerwin32 + // *FIX:Mani - move this down in llappviewerwin32 #ifdef LL_WINDOWS DWORD thread_id = GetCurrentThreadId(); gDebugInfo["MainloopThreadID"] = (S32)thread_id; @@ -2415,11 +2551,19 @@ void LLAppViewer::writeSystemInfo() // If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze, // then the value of "CrashNotHandled" will be set to true. gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; + + // Insert crash host url (url to post crash log to) if configured. This insures + // that the crash report will go to the proper location in the case of a + // prior freeze. + std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } // Dump some debugging info - LL_INFOS("SystemInfo") << LLTrans::getString("SECOND_LIFE_VIEWER") - << " version " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH - << LL_ENDL; + LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") + << " version " << LLVersionInfo::getShortVersion() << LL_ENDL; // Dump the local time and time zone time_t now; @@ -2437,17 +2581,12 @@ void LLAppViewer::writeSystemInfo() writeDebugInfo(); // Save out debug_info.log early, in case of crash. } -void LLAppViewer::handleSyncViewerCrash() -{ - LLAppViewer* pApp = LLAppViewer::instance(); - // Call to pure virtual, handled by platform specific llappviewer instance. - pApp->handleSyncCrashTrace(); -} - void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; + llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ; + //print out recorded call stacks if there are any. LLError::LLCallStacks::print(); @@ -2465,18 +2604,22 @@ void LLAppViewer::handleViewerCrash() return; } pApp->mReportedCrash = TRUE; - - // Make sure the watchdog gets turned off... -// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. + + // Insert crash host url (url to post crash log to) if configured. + std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); - gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR; - gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR; - gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH; - gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD; + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild(); LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if ( parcel && parcel->getMusicURL()[0]) @@ -2499,6 +2642,12 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); + char *minidump_file = pApp->getMiniDumpFilename(); + if(minidump_file && minidump_file[0] != 0) + { + gDebugInfo["MinidumpPath"] = minidump_file; + } + if(gLogoutInProgress) { gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; @@ -2569,17 +2718,13 @@ void LLAppViewer::handleViewerCrash() gMessageSystem->stopLogging(); } - LLWorld::getInstance()->getInfo(gDebugInfo); + if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo); // Close the debug file pApp->writeDebugInfo(); LLError::logToFile(""); -// On Mac, we send the report on the next run, since we need macs crash report -// for a stack trace, so we have to let it the app fail. -#if !LL_DARWIN - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) { @@ -2592,8 +2737,6 @@ void LLAppViewer::handleViewerCrash() // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); - -#endif //!LL_DARWIN return; } @@ -2687,7 +2830,7 @@ void LLAppViewer::initMarkerFile() // Create the marker file for this execution & lock it apr_status_t s; - s = mMarkerFile.open(mMarkerFileName, LL_APR_W, gAPRPoolp); + s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE); if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) { @@ -2755,6 +2898,8 @@ void LLAppViewer::requestQuit() gFloaterView->closeAllChildren(true); } + LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit")); + send_stats(); gLogoutTimer.reset(); @@ -2763,7 +2908,7 @@ void LLAppViewer::requestQuit() static bool finish_quit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { @@ -2775,7 +2920,14 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q void LLAppViewer::userQuit() { - LLNotifications::instance().add("ConfirmQuit"); + if (gDisconnected) + { + requestQuit(); + } + else + { + LLNotificationsUtil::add("ConfirmQuit"); + } } static bool finish_early_exit(const LLSD& notification, const LLSD& response) @@ -2788,7 +2940,7 @@ void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions) { llwarns << "app_early_exit: " << name << llendl; gDoDisconnect = TRUE; - LLNotifications::instance().add(name, substitutions, LLSD(), finish_early_exit); + LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit); } void LLAppViewer::forceExit(S32 arg) @@ -2874,66 +3026,134 @@ void LLAppViewer::migrateCacheDirectory() #endif // LL_WINDOWS || LL_DARWIN } -bool LLAppViewer::initCache() +void dumpVFSCaches() { - mPurgeCache = false; - // Purge cache if user requested it - if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || - gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) + llinfos << "======= Static VFS ========" << llendl; + gStaticVFS->listFiles(); +#if LL_WINDOWS + llinfos << "======= Dumping static VFS to StaticVFSDump ========" << llendl; + WCHAR w_str[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, w_str); + S32 res = LLFile::mkdir("StaticVFSDump"); + if (res == -1) { - gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); - mPurgeCache = true; + if (errno != EEXIST) + { + llwarns << "Couldn't create dir StaticVFSDump" << llendl; + } } - // Purge cache if it belongs to an old version - else + SetCurrentDirectory(utf8str_to_utf16str("StaticVFSDump").c_str()); + gStaticVFS->dumpFiles(); + SetCurrentDirectory(w_str); +#endif + + llinfos << "========= Dynamic VFS ====" << llendl; + gVFS->listFiles(); +#if LL_WINDOWS + llinfos << "========= Dumping dynamic VFS to VFSDump ====" << llendl; + res = LLFile::mkdir("VFSDump"); + if (res == -1) { - static const S32 cache_version = 5; - if (gSavedSettings.getS32("LocalCacheVersion") != cache_version) + if (errno != EEXIST) { - mPurgeCache = true; - gSavedSettings.setS32("LocalCacheVersion", cache_version); + llwarns << "Couldn't create dir VFSDump" << llendl; } } - - // We have moved the location of the cache directory over time. - migrateCacheDirectory(); + SetCurrentDirectory(utf8str_to_utf16str("VFSDump").c_str()); + gVFS->dumpFiles(); + SetCurrentDirectory(w_str); +#endif +} + +//static +U32 LLAppViewer::getTextureCacheVersion() +{ + //viewer texture cache version, change if the texture cache format changes. + const U32 TEXTURE_CACHE_VERSION = 7; + + return TEXTURE_CACHE_VERSION ; +} + +//static +U32 LLAppViewer::getObjectCacheVersion() +{ + // Viewer object cache version, change if object update + // format changes. JC + const U32 INDRA_OBJECT_CACHE_VERSION = 14; + + return INDRA_OBJECT_CACHE_VERSION; +} + +bool LLAppViewer::initCache() +{ + mPurgeCache = false; + BOOL read_only = mSecondInstance ? TRUE : FALSE; + LLAppViewer::getTextureCache()->setReadOnly(read_only) ; + LLVOCache::getInstance()->setReadOnly(read_only); - // Setup and verify the cache location - std::string cache_location = gSavedSettings.getString("CacheLocation"); - std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); - if (new_cache_location != cache_location) + BOOL texture_cache_mismatch = FALSE ; + if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) { - gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); - purgeCache(); // purge old cache - gSavedSettings.setString("CacheLocation", new_cache_location); + texture_cache_mismatch = TRUE ; + if(!read_only) + { + gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); + } } + + if(!read_only) + { + // Purge cache if user requested it + if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || + gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) + { + gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); + mPurgeCache = true; + } + + // We have moved the location of the cache directory over time. + migrateCacheDirectory(); + // Setup and verify the cache location + std::string cache_location = gSavedSettings.getString("CacheLocation"); + std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); + if (new_cache_location != cache_location) + { + gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); + purgeCache(); // purge old cache + gSavedSettings.setString("CacheLocation", new_cache_location); + gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location)); + } + } + if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"))) { LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL; gSavedSettings.setString("CacheLocation", ""); + gSavedSettings.setString("CacheLocationTopFolder", ""); } - if (mPurgeCache) + if (mPurgeCache && !read_only) { - LLSplashScreen::update("Clearing cache..."); + LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); purgeCache(); } - LLSplashScreen::update("Initializing Texture Cache..."); + LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); // Init the texture cache - // Allocate 80% of the cache size for textures - BOOL read_only = mSecondInstance ? TRUE : FALSE; + // Allocate 80% of the cache size for textures const S32 MB = 1024*1024; S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB; const S64 MAX_CACHE_SIZE = 1024*MB; cache_size = llmin(cache_size, MAX_CACHE_SIZE); S64 texture_cache_size = ((cache_size * 8)/10); - S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, read_only); + S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); texture_cache_size -= extra; - LLSplashScreen::update("Initializing VFS..."); + LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ; + + LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS")); // Init the VFS S64 vfs_size = cache_size - texture_cache_size; @@ -3079,6 +3299,14 @@ bool LLAppViewer::initCache() else { LLVFile::initClass(); + +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (gSavedSettings.getBOOL("DumpVFSCaches")) + { + dumpVFSCaches(); + } +#endif + return true; } } @@ -3087,13 +3315,14 @@ void LLAppViewer::purgeCache() { LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); + LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); std::string mask = gDirUtilp->getDirDelimiter() + "*.*"; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask); } std::string LLAppViewer::getSecondLifeTitle() const { - return LLTrans::getString("SECOND_LIFE_VIEWER"); + return LLTrans::getString("APP_NAME"); } std::string LLAppViewer::getWindowTitle() const @@ -3104,7 +3333,7 @@ std::string LLAppViewer::getWindowTitle() const // Callback from a dialog indicating user was logged out. bool finish_disconnect(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (1 == option) { @@ -3144,12 +3373,12 @@ void LLAppViewer::forceDisconnect(const std::string& mesg) { // Tell users what happened args["ERROR_MESSAGE"] = big_reason; - LLNotifications::instance().add("ErrorMessage", args, LLSD(), &finish_forced_disconnect); + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect); } else { args["MESSAGE"] = big_reason; - LLNotifications::instance().add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect ); + LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect ); } } @@ -3163,13 +3392,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; -#if LL_WINDOWS - // Generates the minidump. - LLWinDebug::generateCrashStacks(NULL); -#endif - LLAppViewer::handleSyncViewerCrash(); - LLAppViewer::handleViewerCrash(); - std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" @@ -3182,6 +3404,8 @@ void LLAppViewer::badNetworkHandler() "If the problem continues, see the Tech Support FAQ at: \n" "www.secondlife.com/support"; forceDisconnect(message.str()); + + LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. @@ -3191,10 +3415,10 @@ void LLAppViewer::saveFinalSnapshot() { if (!mSavedFinalSnapshot && !gNoRender) { - gSavedSettings.setVector3d("FocusPosOnLogout", gAgent.calcFocusPositionTargetGlobal()); - gSavedSettings.setVector3d("CameraPosOnLogout", gAgent.calcCameraPositionTargetGlobal()); + gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal()); + gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal()); gViewerWindow->setCursor(UI_CURSOR_WAIT); - gAgent.changeCameraToThirdPerson( FALSE ); // don't animate, need immediate switch + gAgentCamera.changeCameraToThirdPerson( FALSE ); // don't animate, need immediate switch gSavedSettings.setBOOL("ShowParcelOwners", FALSE); idle(); @@ -3202,7 +3426,7 @@ void LLAppViewer::saveFinalSnapshot() snap_filename += gDirUtilp->getDirDelimiter(); snap_filename += SCREEN_LAST_FILENAME; // use full pixel dimensions of viewer window (not post-scale dimensions) - gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE); + gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, TRUE); mSavedFinalSnapshot = TRUE; } } @@ -3258,6 +3482,15 @@ public: } }; +static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio"); +static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup"); +static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks"); +static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD"); +static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist"); +static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region"); +static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World"); +static LLFastTimer::DeclareTimer FTM_NETWORK("Network"); + /////////////////////////////////////////////////////// // idle() // @@ -3313,10 +3546,13 @@ void LLAppViewer::idle() if (LLStartUp::getStartupState() < STATE_STARTED) { // Skip rest if idle startup returns false (essentially, no world yet) + gGLActive = TRUE; if (!idle_startup()) { + gGLActive = FALSE; return; } + gGLActive = FALSE; } @@ -3324,7 +3560,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(LLFastTimer::FTM_NETWORK); + LLFastTimer t(FTM_NETWORK); // Update spaceserver timeinfo LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC)); @@ -3339,9 +3575,12 @@ void LLAppViewer::idle() gAgent.moveYaw(-1.f); } - // Handle automatic walking towards points - gAgentPilot.updateTarget(); - gAgent.autoPilot(&yaw); + { + LLFastTimer t(FTM_AGENT_AUTOPILOT); + // Handle automatic walking towards points + gAgentPilot.updateTarget(); + gAgent.autoPilot(&yaw); + } static LLFrameTimer agent_update_timer; static U32 last_control_flags; @@ -3352,6 +3591,7 @@ void LLAppViewer::idle() if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND))) { + LLFastTimer t(FTM_AGENT_UPDATE); // Send avatar and camera info last_control_flags = gAgent.getControlFlags(); send_agent_update(TRUE); @@ -3405,7 +3645,7 @@ void LLAppViewer::idle() if (!gDisconnected) { - LLFastTimer t(LLFastTimer::FTM_NETWORK); + LLFastTimer t(FTM_NETWORK); //////////////////////////////////////////////// // @@ -3415,10 +3655,8 @@ void LLAppViewer::idle() // floating throughout the various object lists. // - stop_glerror(); idleNetwork(); - stop_glerror(); - + // Check for away from keyboard, kick idle agents. idle_afk_check(); @@ -3434,12 +3672,13 @@ void LLAppViewer::idle() // { -// LLFastTimer t(LLFastTimer::FTM_IDLE_CB); +// LLFastTimer t(FTM_IDLE_CB); // Do event notifications if necessary. Yes, we may want to move this elsewhere. gEventNotifier.update(); gIdleCallbacks.callFunctions(); + gInventory.idleNotifyObservers(); } if (gDisconnected) @@ -3463,13 +3702,15 @@ void LLAppViewer::idle() { // Handle pending gesture processing - gGestureManager.update(); + static LLFastTimer::DeclareTimer ftm("Agent Position"); + LLFastTimer t(ftm); + LLGestureMgr::instance().update(); gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY); } { - LLFastTimer t(LLFastTimer::FTM_OBJECTLIST_UPDATE); // Actually "object update" + LLFastTimer t(FTM_OBJECTLIST_UPDATE); if (!(logoutRequestSent() && hasSavedFinalSnapshot())) { @@ -3484,7 +3725,7 @@ void LLAppViewer::idle() // { - LLFastTimer t(LLFastTimer::FTM_CLEANUP); + LLFastTimer t(FTM_CLEANUP); gObjectList.cleanDeadObjects(); LLDrawable::cleanupDeadDrawables(); } @@ -3503,20 +3744,20 @@ void LLAppViewer::idle() // { + static LLFastTimer::DeclareTimer ftm("HUD Effects"); + LLFastTimer t(ftm); LLSelectMgr::getInstance()->updateEffects(); LLHUDManager::getInstance()->cleanupEffects(); LLHUDManager::getInstance()->sendEffects(); } - stop_glerror(); - //////////////////////////////////////// // // Unpack layer data that we've received // { - LLFastTimer t(LLFastTimer::FTM_NETWORK); + LLFastTimer t(FTM_NETWORK); gVLManager.unpackData(); } @@ -3528,7 +3769,7 @@ void LLAppViewer::idle() LLWorld::getInstance()->updateVisibilities(); { const F32 max_region_update_time = .001f; // 1ms - LLFastTimer t(LLFastTimer::FTM_REGION_UPDATE); + LLFastTimer t(FTM_REGION_UPDATE); LLWorld::getInstance()->updateRegions(max_region_update_time); } @@ -3565,7 +3806,6 @@ void LLAppViewer::idle() gWindVec.setVec(0.0f, 0.0f, 0.0f); } } - stop_glerror(); ////////////////////////////////////// // @@ -3575,12 +3815,11 @@ void LLAppViewer::idle() if (!gNoRender) { - LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE); + LLFastTimer t(FTM_WORLD_UPDATE); gPipeline.updateMove(); LLWorld::getInstance()->updateParticles(); } - stop_glerror(); if (LLViewerJoystick::getInstance()->getOverrideCamera()) { @@ -3593,17 +3832,20 @@ void LLAppViewer::idle() LLViewerJoystick::getInstance()->moveObjects(); } - gAgent.updateCamera(); + gAgentCamera.updateCamera(); } + // update media focus + LLViewerMediaFocus::getInstance()->update(); + // objects and camera should be in sync, do LOD calculations now { - LLFastTimer t(LLFastTimer::FTM_LOD_UPDATE); + LLFastTimer t(FTM_LOD_UPDATE); gObjectList.updateApparentAngles(gAgent); } { - LLFastTimer t(LLFastTimer::FTM_AUDIO_UPDATE); + LLFastTimer t(FTM_AUDIO_UPDATE); if (gAudiop) { @@ -3622,10 +3864,9 @@ void LLAppViewer::idle() // forcibly quit if it has taken too long if (mQuitRequested) { + gGLActive = TRUE; idleShutdown(); } - - stop_glerror(); } void LLAppViewer::idleShutdown() @@ -3649,6 +3890,24 @@ void LLAppViewer::idleShutdown() return; } + if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit"))) + { + return; + } + + + + // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup() + // *TODO: ugly + static bool saved_teleport_history = false; + if (!saved_teleport_history) + { + saved_teleport_history = true; + LLTeleportHistory::getInstance()->dump(); + LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this + return; + } + static bool saved_snapshot = false; if (!saved_snapshot) { @@ -3671,7 +3930,7 @@ void LLAppViewer::idleShutdown() S32 finished_uploads = total_uploads - pending_uploads; F32 percent = 100.f * finished_uploads / total_uploads; gViewerWindow->setProgressPercent(percent); - gViewerWindow->setProgressString("Saving your settings..."); + gViewerWindow->setProgressString(LLTrans::getString("SavingSettings")); return; } @@ -3683,7 +3942,7 @@ void LLAppViewer::idleShutdown() // Wait for a LogoutReply message gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(100.f); - gViewerWindow->setProgressString("Logging out..."); + gViewerWindow->setProgressString(LLTrans::getString("LoggingOut")); return; } @@ -3711,7 +3970,7 @@ void LLAppViewer::sendLogoutRequest() gLogoutMaxTime = LOGOUT_REQUEST_TIME; mLogoutRequestSent = TRUE; - gVoiceClient->leaveChannel(); + LLVoiceClient::getInstance()->leaveChannel(); //Set internal status variables and marker files gLogoutInProgress = TRUE; @@ -3743,26 +4002,24 @@ void LLAppViewer::sendLogoutRequest() static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; #endif +static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network"); + void LLAppViewer::idleNetwork() { LLMemType mt_in(LLMemType::MTYPE_IDLE_NETWORK); pingMainloopTimeout("idleNetwork"); - LLError::LLCallStacks::clear() ; - llpushcallstacks ; - + gObjectList.mNumNewObjects = 0; S32 total_decoded = 0; if (!gSavedSettings.getBOOL("SpeedTest")) { - LLFastTimer t(LLFastTimer::FTM_IDLE_NETWORK); // decode + LLFastTimer t(FTM_IDLE_NETWORK); // decode // deal with any queued name requests and replies. gCacheName->processPending(); - llpushcallstacks ; LLTimer check_message_timer; // Read all available packets from network - stop_glerror(); const S64 frame_count = gFrameCount; // U32->S64 F32 total_time = 0.0f; @@ -3775,8 +4032,7 @@ void LLAppViewer::idleNetwork() // server going down, so this is OK. break; } - stop_glerror(); - + total_decoded++; gPacketsIn++; @@ -3816,9 +4072,7 @@ void LLAppViewer::idleNetwork() // we want to clear the control after sending out all necessary agent updates gAgent.resetControlFlags(); - stop_glerror(); - - + // Decode enqueued messages... S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded; @@ -3833,16 +4087,13 @@ void LLAppViewer::idleNetwork() gPrintMessagesThisFrame = FALSE; } } - llpushcallstacks ; LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); // Retransmit unacknowledged packets. gXferManager->retransmitUnackedPackets(); gAssetStorage->checkForTimeouts(); - llpushcallstacks ; gViewerThrottle.updateDynamicThrottle(); - llpushcallstacks ; // Check that the circuit between the viewer and the agent's current // region is still alive LLViewerRegion *agent_region = gAgent.getRegion(); @@ -3858,7 +4109,6 @@ void LLAppViewer::idleNetwork() mAgentRegionLastID = this_region_id; mAgentRegionLastAlive = this_region_alive; } - llpushcallstacks ; } void LLAppViewer::disconnectViewer() @@ -3893,23 +4143,23 @@ void LLAppViewer::disconnectViewer() LLSelectMgr::getInstance()->deselectAll(); } - if (!gNoRender) + // save inventory if appropriate + gInventory.cache(gInventory.getRootFolderID(), gAgent.getID()); + if (gInventory.getLibraryRootFolderID().notNull() + && gInventory.getLibraryOwnerID().notNull()) { - // save inventory if appropriate - gInventory.cache(gAgent.getInventoryRootID(), gAgent.getID()); - if(gInventoryLibraryRoot.notNull() && gInventoryLibraryOwner.notNull()) - { - gInventory.cache(gInventoryLibraryRoot, gInventoryLibraryOwner); - } + gInventory.cache( + gInventory.getLibraryRootFolderID(), + gInventory.getLibraryOwnerID()); } saveNameCache(); // close inventory interface, close all windows - LLInventoryView::cleanup(); + LLFloaterInventory::cleanup(); gAgentWearables.cleanup(); - + gAgentCamera.cleanup(); // Also writes cached agent settings to gSavedSettings gAgent.cleanup(); @@ -3940,11 +4190,11 @@ void LLAppViewer::forceErrorBreakpoint() void LLAppViewer::forceErrorBadMemoryAccess() { S32* crash = NULL; - *crash = 0xDEADBEEF; + *crash = 0xDEADBEEF; return; } -void LLAppViewer::forceErrorInifiniteLoop() +void LLAppViewer::forceErrorInfiniteLoop() { while(true) { @@ -4025,17 +4275,15 @@ void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs) void LLAppViewer::handleLoginComplete() { - gViewerWindow->handleLoginComplete(); - initMainloopTimeout("Mainloop Init"); // Store some data to DebugInfo in case of a freeze. gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); - gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR; - gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR; - gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH; - gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD; + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild(); LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if ( parcel && parcel->getMusicURL()[0]) @@ -4062,5 +4310,215 @@ void LLAppViewer::handleLoginComplete() { gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); } + + mOnLoginCompleted(); + writeDebugInfo(); } + +// *TODO - generalize this and move DSO wrangling to a helper class -brad +void LLAppViewer::loadEventHostModule(S32 listen_port) +{ + std::string dso_name = +#if LL_WINDOWS + "lleventhost.dll"; +#elif LL_DARWIN + "liblleventhost.dylib"; +#else + "liblleventhost.so"; +#endif + + std::string dso_path = gDirUtilp->findFile(dso_name, + gDirUtilp->getAppRODataDir(), + gDirUtilp->getExecutableDir()); + + if(dso_path == "") + { + llerrs << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl; + return; + } + + apr_dso_handle_t * eventhost_dso_handle = NULL; + apr_pool_t * eventhost_dso_memory_pool = NULL; + + //attempt to load the shared library + apr_pool_create(&eventhost_dso_memory_pool, NULL); + apr_status_t rv = apr_dso_load(&eventhost_dso_handle, + dso_path.c_str(), + eventhost_dso_memory_pool); + ll_apr_assert_status(rv); + llassert_always(eventhost_dso_handle != NULL); + + int (*ll_plugin_start_func)(LLSD const &) = NULL; + rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start"); + + ll_apr_assert_status(rv); + llassert_always(ll_plugin_start_func != NULL); + + LLSD args; + args["listen_port"] = listen_port; + + int status = ll_plugin_start_func(args); + + if(status != 0) + { + llerrs << "problem loading eventhost plugin, status: " << status << llendl; + } + + mPlugins.insert(eventhost_dso_handle); +} + +void LLAppViewer::launchUpdater() +{ + LLSD query_map = LLSD::emptyMap(); + // *TODO place os string in a global constant +#if LL_WINDOWS + query_map["os"] = "win"; +#elif LL_DARWIN + query_map["os"] = "mac"; +#elif LL_LINUX + query_map["os"] = "lnx"; +#elif LL_SOLARIS + query_map["os"] = "sol"; +#endif + // *TODO change userserver to be grid on both viewer and sim, since + // userserver no longer exists. + query_map["userserver"] = LLGridManager::getInstance()->getGridLabel(); + query_map["channel"] = gSavedSettings.getString("VersionChannelName"); + // *TODO constantize this guy + // *NOTE: This URL is also used in win_setup/lldownloader.cpp + LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map); + + if(LLAppViewer::sUpdaterInfo) + { + delete LLAppViewer::sUpdaterInfo; + } + LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ; + + // if a sim name was passed in via command line parameter (typically through a SLURL) + if ( LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION ) + { + // record the location to start at next time + gSavedSettings.setString( "NextLoginLocation", LLStartUp::getStartSLURL().getSLURLString()); + }; + +#if LL_WINDOWS + LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename(); + if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty()) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + // We're hosed, bail + LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL; + return; + } + + LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe"; + + std::string updater_source = gDirUtilp->getAppRODataDir(); + updater_source += gDirUtilp->getDirDelimiter(); + updater_source += "updater.exe"; + + LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source + << " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath + << LL_ENDL; + + + if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE)) + { + delete LLAppViewer::sUpdaterInfo ; + LLAppViewer::sUpdaterInfo = NULL ; + + LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL; + + return; + } + + LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\""; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL; + + //Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird. + LLAppViewer::instance()->removeMarkerFile(); // In case updater fails + + // *NOTE:Mani The updater is spawned as the last thing before the WinMain exit. + // see LLAppViewerWin32.cpp + +#elif LL_DARWIN + LLAppViewer::sUpdaterInfo->mUpdateExePath = "'"; + LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \""; + LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle(); + LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &"; + + LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; + + // Run the auto-updater. + system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */ + +#elif (LL_LINUX || LL_SOLARIS) && LL_GTK + // we tell the updater where to find the xml containing string + // translations which it can use for its own UI + std::string xml_strings_file = "strings.xml"; + std::vector<std::string> xui_path_vec = LLUI::getXUIPaths(); + std::string xml_search_paths; + std::vector<std::string>::const_iterator iter; + // build comma-delimited list of xml paths to pass to updater + for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) + { + std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() + + gDirUtilp->getDirDelimiter() + + (*iter); + llinfos << "Got a XUI path: " << this_skin_dir << llendl; + xml_search_paths.append(this_skin_dir); + ++iter; + if (iter != xui_path_vec.end()) + xml_search_paths.append(","); // comma-delimit + } + // build the overall command-line to run the updater correctly + LLAppViewer::sUpdaterInfo->mUpdateExePath = + gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + + " --url \"" + update_url.asString() + "\"" + + " --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" + + " --dest \"" + gDirUtilp->getAppRODataDir() + "\"" + + " --stringsdir \"" + xml_search_paths + "\"" + + " --stringsfile \"" + xml_strings_file + "\""; + + LL_INFOS("AppInit") << "Calling updater: " + << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL; + + // *TODO: we could use the gdk equivalent to ensure the updater + // gets started on the same screen. + GError *error = NULL; + if (!g_spawn_command_line_async(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), &error)) + { + llerrs << "Failed to launch updater: " + << error->message + << llendl; + } + if (error) { + g_error_free(error); + } +#else + OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK); +#endif + + // *REMOVE:Mani - Saving for reference... + // LLAppViewer::instance()->forceQuit(); +} + + +//virtual +void LLAppViewer::setMasterSystemAudioMute(bool mute) +{ + gSavedSettings.setBOOL("MuteAudio", mute); +} + +//virtual +bool LLAppViewer::getMasterSystemAudioMute() +{ + return gSavedSettings.getBOOL("MuteAudio"); +} |