00001
00033 #include "llviewerprecompiledheaders.h"
00034 #include "llappviewer.h"
00035 #include "llprimitive.h"
00036
00037 #include "llversionviewer.h"
00038 #include "llfeaturemanager.h"
00039 #include "lluictrlfactory.h"
00040 #include "llalertdialog.h"
00041 #include "llerrorcontrol.h"
00042 #include "llviewerimagelist.h"
00043 #include "llgroupmgr.h"
00044 #include "llagent.h"
00045 #include "llwindow.h"
00046 #include "llviewerstats.h"
00047 #include "llmd5.h"
00048 #include "llpumpio.h"
00049 #include "llimpanel.h"
00050 #include "llmimetypes.h"
00051 #include "llstartup.h"
00052 #include "llfocusmgr.h"
00053 #include "llviewerjoystick.h"
00054 #include "llfloaterjoystick.h"
00055 #include "llares.h"
00056 #include "llcurl.h"
00057 #include "llfloatersnapshot.h"
00058 #include "llviewerwindow.h"
00059 #include "llviewerdisplay.h"
00060 #include "llviewermessage.h"
00061 #include "llviewerobjectlist.h"
00062 #include "llworldmap.h"
00063 #include "llmutelist.h"
00064 #include "llurldispatcher.h"
00065 #include "llurlhistory.h"
00066 #include "llfirstuse.h"
00067 #include "llglimmediate.h"
00068
00069 #include "llweb.h"
00070 #include "llsecondlifeurls.h"
00071
00072 #include <boost/bind.hpp>
00073
00074 #if LL_WINDOWS
00075 #include "llwindebug.h"
00076 #endif
00077
00078 #if LL_WINDOWS
00079 # include <share.h>
00080 #else
00081 # include <sys/file.h>
00082 #endif
00083
00084
00085
00086 #include "llnotify.h"
00087 #include "llviewerkeyboard.h"
00088 #include "lllfsthread.h"
00089 #include "llworkerthread.h"
00090 #include "lltexturecache.h"
00091 #include "lltexturefetch.h"
00092 #include "llimageworker.h"
00093
00094
00095 #include "llkeyframemotion.h"
00096 #include "llworldmap.h"
00097 #include "llhudmanager.h"
00098 #include "lltoolmgr.h"
00099 #include "llassetstorage.h"
00100 #include "llpolymesh.h"
00101 #include "llcachename.h"
00102 #include "audioengine.h"
00103 #include "llviewermenu.h"
00104 #include "llselectmgr.h"
00105 #include "lltrans.h"
00106 #include "lltracker.h"
00107 #include "llviewerparcelmgr.h"
00108 #include "llworldmapview.h"
00109 #include "llpostprocess.h"
00110 #include "llwlparammanager.h"
00111 #include "llwaterparammanager.h"
00112
00113 #include "lldebugview.h"
00114 #include "llconsole.h"
00115 #include "llcontainerview.h"
00116 #include "llfloaterstats.h"
00117 #include "llhoverview.h"
00118
00119 #include "llsdserialize.h"
00120
00121 #include "llworld.h"
00122 #include "llhudeffecttrail.h"
00123 #include "llvectorperfoptions.h"
00124 #include "llurlsimstring.h"
00125 #include "llwatchdog.h"
00126
00127
00128
00129 #include "llbutton.h"
00130 #include "llcombobox.h"
00131 #include "llstatusbar.h"
00132 #include "llsurface.h"
00133 #include "llvosky.h"
00134 #include "llvotree.h"
00135 #include "llvoavatar.h"
00136 #include "llfolderview.h"
00137 #include "lltoolbar.h"
00138 #include "llframestats.h"
00139 #include "llagentpilot.h"
00140 #include "llsrv.h"
00141 #include "llvovolume.h"
00142 #include "llflexibleobject.h"
00143 #include "llvosurfacepatch.h"
00144
00145
00146 #include "llviewercontrol.h"
00147 #include "lleventnotifier.h"
00148 #include "llcallbacklist.h"
00149 #include "pipeline.h"
00150 #include "llgesturemgr.h"
00151 #include "llsky.h"
00152 #include "llvlmanager.h"
00153 #include "llviewercamera.h"
00154 #include "lldrawpoolbump.h"
00155 #include "llvieweraudio.h"
00156 #include "llimview.h"
00157 #include "llviewerthrottle.h"
00158 #include "llparcel.h"
00159
00160
00161 #include "llinventoryview.h"
00162
00163 #include "llcommandlineparser.h"
00164
00165
00166 #if LL_LINUX
00167 # define LL_DYNAMIC_FONT_DISCOVERY 1
00168 #else
00169 # define LL_DYNAMIC_FONT_DISCOVERY 0
00170 #endif
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 #include "llviewernetwork.h"
00183
00184
00186
00187 #if LL_WINDOWS && LL_LCD_COMPILE
00188 #include "lllcd.h"
00189 #endif
00190
00191
00192
00193 extern void disable_win_error_reporting();
00194
00195
00196 #if LL_RELEASE_FOR_DOWNLOAD
00197
00198 #ifndef APPLE_PREVIEW
00199 static EGridInfo GridDefaultChoice = GRID_INFO_AGNI;
00200 #else
00201 static EGridInfo GridDefaultChoice = GRID_INFO_ADITI;
00202 #endif
00203 #else
00204
00205 static EGridInfo GridDefaultChoice = GRID_INFO_NONE;
00206 #endif
00207
00208 #if LL_WINDOWS
00209 extern void create_console();
00210 #endif
00211
00212
00213 #if LL_DARWIN
00214 #include <Carbon/Carbon.h>
00215 extern void init_apple_menu(const char* product);
00216 extern OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
00217 extern OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
00218 extern OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata);
00219 extern OSStatus DisplayReleaseNotes(void);
00220 #include <boost/tokenizer.hpp>
00221 #endif // LL_DARWIN
00222
00223
00224 extern BOOL gRandomizeFramerate;
00225 extern BOOL gPeriodicSlowFrame;
00226 extern BOOL gDebugGL;
00227
00229
00230 BOOL gHandleKeysAsync = FALSE;
00231
00232 const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f;
00233
00234 F32 gSimLastTime;
00235 F32 gSimFrames;
00236
00237 LLString gDisabledMessage;
00238
00239 BOOL gHideLinks = FALSE;
00240
00241 BOOL gAllowIdleAFK = TRUE;
00242 BOOL gAllowTapTapHoldRun = TRUE;
00243 BOOL gShowObjectUpdates = FALSE;
00244 BOOL gUseQuickTime = TRUE;
00245
00246 BOOL gAcceptTOS = FALSE;
00247 BOOL gAcceptCriticalMessage = FALSE;
00248
00249 eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
00250
00251 LLSD gDebugInfo;
00252
00253 U32 gFrameCount = 0;
00254 U32 gForegroundFrameCount = 0;
00255 LLPumpIO* gServicePump = NULL;
00256
00257 BOOL gPacificDaylightTime = FALSE;
00258
00259 U64 gFrameTime = 0;
00260 F32 gFrameTimeSeconds = 0.f;
00261 F32 gFrameIntervalSeconds = 0.f;
00262 F32 gFPSClamped = 10.f;
00263 F32 gFrameDTClamped = 0.f;
00264 U64 gStartTime = 0;
00265
00266 LLTimer gRenderStartTime;
00267 LLFrameTimer gForegroundTime;
00268 LLTimer gLogoutTimer;
00269 static const F32 LOGOUT_REQUEST_TIME = 6.f;
00270 F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
00271
00272 LLUUID gInventoryLibraryOwner;
00273 LLUUID gInventoryLibraryRoot;
00274
00275 BOOL gDisconnected = FALSE;
00276
00277
00278 F32 gMapScale = 128.f;
00279 F32 gMiniMapScale = 128.f;
00280
00281
00282 LLFrameTimer gRestoreGLTimer;
00283 BOOL gRestoreGL = FALSE;
00284 BOOL gUseWireframe = FALSE;
00285
00286
00287 LLVFS* gStaticVFS = NULL;
00288
00289 LLMemoryInfo gSysMemory;
00290
00291 LLString gLastVersionChannel;
00292
00293 LLVector3 gWindVec(3.0, 3.0, 0.0);
00294 LLVector3 gRelativeWindVec(0.0, 0.0, 0.0);
00295
00296 U32 gPacketsIn = 0;
00297
00298 BOOL gPrintMessagesThisFrame = FALSE;
00299
00300 BOOL gRandomizeFramerate = FALSE;
00301 BOOL gPeriodicSlowFrame = FALSE;
00302
00303 BOOL gCrashOnStartup = FALSE;
00304 BOOL gLLErrorActivated = FALSE;
00305 BOOL gLogoutInProgress = FALSE;
00307
00308 static LLString gArgs;
00309
00310 const char* MARKER_FILE_NAME = "SecondLife.exec_marker";
00311 const char* ERROR_MARKER_FILE_NAME = "SecondLife.error_marker";
00312 const char* LLERROR_MARKER_FILE_NAME = "SecondLife.llerror_marker";
00313 const char* LOGOUT_MARKER_FILE_NAME = "SecondLife.logout_marker";
00314 static BOOL gDoDisconnect = FALSE;
00315 static LLString gLaunchFileOnQuit;
00316
00317
00318
00319 const char *VFS_DATA_FILE_BASE = "data.db2.x.";
00320 const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
00321
00322 static LLString gSecondLife;
00323 static LLString gWindowTitle;
00324 #ifdef LL_WINDOWS
00325 static char sWindowClass[] = "Second Life";
00326 #endif
00327
00328 std::string gLoginPage;
00329 std::vector<std::string> gLoginURIs;
00330 static std::string gHelperURI;
00331
00332 void idle_afk_check()
00333 {
00334
00335 if (gAllowIdleAFK && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getF32("AFKTimeout")))
00336 {
00337 gAgent.setAFK();
00338 }
00339 }
00340
00341
00342 static void ui_audio_callback(const LLUUID& uuid)
00343 {
00344 if (gAudiop)
00345 {
00346 F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI");
00347 gAudiop->triggerSound(uuid, gAgent.getID(), volume);
00348 }
00349 }
00350
00351 void request_initial_instant_messages()
00352 {
00353 static BOOL requested = FALSE;
00354 if (!requested
00355 && gMessageSystem
00356 && LLMuteList::getInstance()->isLoaded()
00357 && gAgent.getAvatarObject())
00358 {
00359
00360
00361
00362 LLMessageSystem* msg = gMessageSystem;
00363 msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
00364 msg->nextBlockFast(_PREHASH_AgentData);
00365 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00366 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00367 gAgent.sendReliableMessage();
00368 requested = TRUE;
00369 }
00370 }
00371
00372
00373
00374 static void settings_to_globals()
00375 {
00376 LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad");
00377 LLBUTTON_V_PAD = gSavedSettings.getS32("ButtonVPad");
00378 BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall");
00379 BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight");
00380
00381 MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
00382 MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
00383 STATUS_BAR_HEIGHT = gSavedSettings.getS32("StatusBarHeight");
00384
00385 LLCOMBOBOX_HEIGHT = BTN_HEIGHT - 2;
00386 LLCOMBOBOX_WIDTH = 128;
00387
00388 LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
00389
00390 LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
00391 LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor");
00392 LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f;
00393 LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
00394 LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
00395 LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor");
00396 LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible");
00397 LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
00398
00399 LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
00400 LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay");
00401 LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
00402 LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
00403 LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
00404
00405 gFrameStats.setTrackStats(gSavedSettings.getBOOL("StatsSessionTrackFrameStats"));
00406 gAgentPilot.mNumRuns = gSavedSettings.getS32("StatsNumRuns");
00407 gAgentPilot.mQuitAfterRuns = gSavedSettings.getBOOL("StatsQuitAfterRuns");
00408 gAgent.mHideGroupTitle = gSavedSettings.getBOOL("RenderHideGroupTitle");
00409
00410 gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
00411 gAllowIdleAFK = gSavedSettings.getBOOL("AllowIdleAFK");
00412 gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
00413 gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
00414 gMapScale = gSavedSettings.getF32("MapScale");
00415 gMiniMapScale = gSavedSettings.getF32("MiniMapScale");
00416 gHandleKeysAsync = gSavedSettings.getBOOL("AsyncKeyboard");
00417 LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
00418 }
00419
00420 static void settings_modify()
00421 {
00422 LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderUseFBO");
00423 LLVOAvatar::sUseImpostors = gSavedSettings.getBOOL("RenderUseImpostors");
00424 LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
00425 LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor;
00426 gDebugGL = gSavedSettings.getBOOL("RenderDebugGL");
00427 gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
00428
00429 #if LL_VECTORIZE
00430 if (gSysCPU.hasAltivec())
00431 {
00432 gSavedSettings.setBOOL("VectorizeEnable", TRUE );
00433 gSavedSettings.setU32("VectorizeProcessor", 0 );
00434 }
00435 else
00436 if (gSysCPU.hasSSE2())
00437 {
00438 gSavedSettings.setBOOL("VectorizeEnable", TRUE );
00439 gSavedSettings.setU32("VectorizeProcessor", 2 );
00440 }
00441 else
00442 if (gSysCPU.hasSSE())
00443 {
00444 gSavedSettings.setBOOL("VectorizeEnable", TRUE );
00445 gSavedSettings.setU32("VectorizeProcessor", 1 );
00446 }
00447 else
00448 {
00449
00450 gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
00451 gSavedSettings.setBOOL("VectorizeEnable", FALSE );
00452 gSavedSettings.setU32("VectorizeProcessor", 0 );
00453 gSavedSettings.setBOOL("VectorizeSkin", FALSE);
00454 }
00455 #else
00456
00457 gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
00458 gSavedSettings.setBOOL("VectorizeEnable", FALSE );
00459 gSavedSettings.setU32("VectorizeProcessor", 0 );
00460 gSavedSettings.setBOOL("VectorizeSkin", FALSE);
00461 #endif
00462
00463
00464 gSavedSettings.setBOOL("PTTCurrentlyEnabled", TRUE);
00465 }
00466
00467 void initGridChoice()
00468 {
00469 LLString gridChoice = gSavedSettings.getString("GridChoice");
00470 if(!gridChoice.empty())
00471
00472
00473 {
00474
00475 int gridIndex = GRID_INFO_NONE;
00476 for(;gridIndex < GRID_INFO_OTHER; ++gridIndex )
00477 {
00478 if(0 == LLString::compareInsensitive(gGridInfo[gridIndex].mLabel, gridChoice.c_str()))
00479 {
00480 gGridChoice = (EGridInfo)gridIndex;
00481
00482 if(GRID_INFO_LOCAL == gGridChoice)
00483 {
00484 gGridName = LOOPBACK_ADDRESS_STRING;
00485 break;
00486 }
00487 else
00488 {
00489 gGridName = gGridInfo[gGridChoice].mName;
00490 break;
00491 }
00492 }
00493 }
00494
00495 if(GRID_INFO_OTHER == gridIndex)
00496 {
00497
00498 gGridChoice = (EGridInfo)gridIndex;
00499 gGridName = llformat("%s", gSavedSettings.getString("GridChoice").c_str());
00500
00501 }
00502 }
00503
00504
00505 #if !LL_RELEASE_FOR_DOWNLOAD
00506 if (gGridChoice == GRID_INFO_NONE)
00507 {
00508
00509 S32 server = gSavedSettings.getS32("ServerChoice");
00510 if (server != 0)
00511 gGridChoice = (EGridInfo)llclamp(server, 0, (S32)GRID_INFO_COUNT - 1);
00512 if (server == GRID_INFO_OTHER)
00513 {
00514 LLString custom_server = gSavedSettings.getString("CustomServer");
00515 if (custom_server.empty())
00516 {
00517 gGridName = "none";
00518 }
00519 else
00520 {
00521 gGridName = custom_server.c_str();
00522 }
00523 }
00524
00525 gSavedSettings.setString("GridChoice", gGridInfo[gGridChoice].mLabel);
00526 }
00527 #endif
00528
00529 if (gGridChoice == GRID_INFO_NONE)
00530 {
00531 gGridChoice = GridDefaultChoice;
00532 gSavedSettings.setString("GridChoice", gGridInfo[gGridChoice].mLabel);
00533 }
00534 }
00535
00536 bool send_url_to_other_instance(const std::string& url)
00537 {
00538 #if LL_WINDOWS
00539 wchar_t window_class[256];
00540 mbstowcs(window_class, sWindowClass, 255);
00541 window_class[255] = 0;
00542
00543 HWND other_window = FindWindow(window_class, NULL);
00544
00545 if (other_window != NULL)
00546 {
00547 lldebugs << "Found other window with the name '" << gWindowTitle << "'" << llendl;
00548 COPYDATASTRUCT cds;
00549 const S32 SLURL_MESSAGE_TYPE = 0;
00550 cds.dwData = SLURL_MESSAGE_TYPE;
00551 cds.cbData = url.length() + 1;
00552 cds.lpData = (void*)url.c_str();
00553
00554 LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&cds);
00555 lldebugs << "SendMessage(WM_COPYDATA) to other window '"
00556 << gWindowTitle << "' returned " << msg_result << llendl;
00557 return true;
00558 }
00559 #endif
00560 return false;
00561 }
00562
00563
00564
00565
00566
00567
00568 LLAppViewer* LLAppViewer::sInstance = NULL;
00569
00570 const std::string LLAppViewer::sGlobalSettingsName = "Global";
00571 const std::string LLAppViewer::sPerAccountSettingsName = "PerAccount";
00572 const std::string LLAppViewer::sCrashSettingsName = "CrashSettings";
00573
00574 LLTextureCache* LLAppViewer::sTextureCache = NULL;
00575 LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL;
00576 LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
00577
00578 LLAppViewer::LLAppViewer() :
00579 mMarkerFile(NULL),
00580 mCrashBehavior(CRASH_BEHAVIOR_ASK),
00581 mReportedCrash(false),
00582 mNumSessions(0),
00583 mPurgeCache(false),
00584 mPurgeOnExit(false),
00585 mSecondInstance(false),
00586 mSavedFinalSnapshot(false),
00587 mQuitRequested(false),
00588 mLogoutRequestSent(false),
00589 mYieldTime(-1)
00590 {
00591 if(NULL != sInstance)
00592 {
00593 llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
00594 }
00595
00596 sInstance = this;
00597
00598
00599 mMainloopTimeout = new LLWatchdogTimeout();
00600 }
00601
00602 LLAppViewer::~LLAppViewer()
00603 {
00604
00605 delete mMainloopTimeout;
00606
00607
00608 removeMarkerFile();
00609 }
00610
00611 bool LLAppViewer::init()
00612 {
00613
00614
00615 LLCurl::initClass();
00616
00617 initThreads();
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 gDirUtilp->initAppDirs("SecondLife");
00631
00632
00633 initLogging();
00634
00635
00636
00637
00638 if (!initConfiguration())
00639 return false;
00640
00641 writeSystemInfo();
00642
00643
00644 gCurrentVersion = llformat("%s %d.%d.%d.%d",
00645 gSavedSettings.getString("VersionChannelName").c_str(),
00646 LL_VERSION_MAJOR,
00647 LL_VERSION_MINOR,
00648 LL_VERSION_PATCH,
00649 LL_VERSION_BUILD );
00650
00655
00656
00657
00658
00659
00660 LL_DEBUGS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
00661
00662
00663 std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
00664 gCrashSettings.loadFromFile(crash_settings_filename.c_str());
00665
00667
00669 #if LL_WINDOWS
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 #endif
00688
00689
00690 mNumSessions = gSavedSettings.getS32("NumSessions");
00691 mNumSessions++;
00692 gSavedSettings.setS32("NumSessions", mNumSessions);
00693
00694 gSavedSettings.setString("HelpLastVisitedURL",gSavedSettings.getString("HelpHomeURL"));
00695
00696 if (gSavedSettings.getBOOL("VerboseLogs"))
00697 {
00698 LLError::setPrintLocation(true);
00699 }
00700
00701
00702 LLString colors_base_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "colors_base.xml");
00703 LL_DEBUGS("InitInfo") << "Loading base colors from " << colors_base_filename << LL_ENDL;
00704 gColors.loadFromFileLegacy(colors_base_filename.c_str(), FALSE, TYPE_COL4U);
00705
00706
00707 LLString user_colors_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "colors.xml");
00708 LL_DEBUGS("InitInfo") << "Loading user colors from " << user_colors_filename << LL_ENDL;
00709 if (gColors.loadFromFileLegacy(user_colors_filename.c_str(), FALSE, TYPE_COL4U) == 0)
00710 {
00711 LL_DEBUGS("InitInfo") << "Cannot load user colors from " << user_colors_filename << LL_ENDL;
00712 }
00713
00714
00715 LLUI::initClass(&gSavedSettings,
00716 &gColors,
00717 LLUIImageList::getInstance(),
00718 ui_audio_callback,
00719 &LLUI::sGLScaleFactor);
00720
00721 LLWeb::initClass();
00722 LLUICtrlFactory::getInstance()->setupPaths();
00723
00725
00726
00727
00728
00729 LLGroupMgr::parseRoleActions("role_actions.xml");
00730
00731 LLAgent::parseTeleportMessages("teleport_strings.xml");
00732
00733 LLViewerJointMesh::updateVectorize();
00734
00735
00736 LLMIMETypes::parseMIMETypes( "mime_types.xml" );
00737
00738
00739
00740 settings_to_globals();
00741
00742 settings_setup_listeners();
00743
00744 settings_modify();
00745
00746
00747 mSerialNumber = generateSerialNumber();
00748
00749 if(false == initHardwareTest())
00750 {
00751
00752 return false;
00753 }
00754
00755
00756
00757 LLUUID::getNodeID(gMACAddress);
00758
00759
00760
00761 #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
00762 MemSetErrorHandler(first_mem_error_handler);
00763 #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
00764
00765
00766
00767
00768
00769
00770
00771 if (!initCache())
00772 {
00773 std::ostringstream msg;
00774 msg <<
00775 gSecondLife << " is unable to access a file that it needs.\n"
00776 "\n"
00777 "This can be because you somehow have multiple copies running, "
00778 "or your system incorrectly thinks a file is open. "
00779 "If this message persists, restart your computer and try again. "
00780 "If it continues to persist, you may need to completely uninstall " <<
00781 gSecondLife << " and reinstall it.";
00782 OSMessageBox(
00783 msg.str().c_str(),
00784 NULL,
00785 OSMB_OK);
00786 return 1;
00787 }
00788
00789
00790
00791
00792 initWindow();
00793
00794 #if LL_WINDOWS && LL_LCD_COMPILE
00795
00796 HINSTANCE hInstance = GetModuleHandle(NULL);
00797 gLcdScreen = new LLLCD(hInstance);
00798 CreateLCDDebugWindows();
00799 #endif
00800
00801 gGLManager.getGLInfo(gDebugInfo);
00802 gGLManager.printGLInfoString();
00803
00804
00805 bind_keyboard_functions();
00806
00807
00808 if (!gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keys.ini").c_str()))
00809 {
00810 LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
00811 }
00812
00813 gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"custom_keys.ini").c_str());
00814
00815
00816 if (!gGLManager.mHasRequirements && !gNoRender)
00817 {
00818
00819
00820 OSMessageBox(
00821 LLAlertDialog::getTemplateMessage("UnsupportedGLRequirements").c_str(),
00822 NULL,
00823 OSMB_OK);
00824 return 0;
00825 }
00826
00827
00828 bool unsupported = false;
00829 LLString::format_map_t args;
00830 LLString minSpecs;
00831
00832
00833 std::stringstream minCPUString(LLAlertDialog::getTemplateMessage("UnsupportedCPUAmount"));
00834 S32 minCPU = 0;
00835 minCPUString >> minCPU;
00836
00837
00838 std::stringstream minRAMString(LLAlertDialog::getTemplateMessage("UnsupportedRAMAmount"));
00839 U64 minRAM = 0;
00840 minRAMString >> minRAM;
00841 minRAM = minRAM * 1024 * 1024;
00842
00843 if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
00844 {
00845 minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedGPU");
00846 minSpecs += "\n";
00847 unsupported = true;
00848 }
00849 if(gSysCPU.getMhz() < minCPU)
00850 {
00851 minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedCPU");
00852 minSpecs += "\n";
00853 unsupported = true;
00854 }
00855 if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
00856 {
00857 minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedRAM");
00858 minSpecs += "\n";
00859 unsupported = true;
00860 }
00861
00862 if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
00863 {
00864 gViewerWindow->alertXml("UnknownGPU");
00865 }
00866
00867 if(unsupported)
00868 {
00869 if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
00870 || gSavedSettings.getBOOL("WarnUnsupportedHardware"))
00871 {
00872 args["MINSPECS"] = minSpecs;
00873 gViewerWindow->alertXml("UnsupportedHardware", args );
00874 }
00875
00876 }
00877
00878
00879 gSavedSettings.setString("LastRunVersion", gCurrentVersion);
00880
00881 gSimLastTime = gRenderStartTime.getElapsedTimeF32();
00882 gSimFrames = (F32)gFrameCount;
00883
00884 LLViewerJoystick::getInstance()->init(false);
00885
00886 return true;
00887 }
00888
00889 bool LLAppViewer::mainLoop()
00890 {
00891 mMainloopTimeout = new LLWatchdogTimeout();
00892
00893 mMainloopTimeout->setTimeout(5);
00894
00895
00896
00897
00898
00899
00900 gServicePump = new LLPumpIO(gAPRPoolp);
00901 LLHTTPClient::setPump(*gServicePump);
00902 LLCurl::setCAFile(gDirUtilp->getCAFile());
00903
00904
00905
00906 LLVoiceChannel::initClass();
00907 LLVoiceClient::init(gServicePump);
00908
00909 LLMemType mt1(LLMemType::MTYPE_MAIN);
00910 LLTimer frameTimer,idleTimer;
00911 LLTimer debugTime;
00912 LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
00913 joystick->setNeedsReset(true);
00914
00915
00916 while (!LLApp::isExiting())
00917 {
00918 LLFastTimer::reset();
00919 try
00920 {
00921 LLFastTimer t(LLFastTimer::FTM_FRAME);
00922
00923 {
00924 LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
00925 #if LL_WINDOWS
00926 if (!LLWinDebug::checkExceptionHandler())
00927 {
00928 llwarns << " Someone took over my exception handler (post messagehandling)!" << llendl;
00929 }
00930 #endif
00931
00932 gViewerWindow->mWindow->gatherInput();
00933 }
00934
00935 #if 1 && !LL_RELEASE_FOR_DOWNLOAD
00936
00937 if (debugTime.getElapsedTimeF32() > 1.f)
00938 {
00939 debugTime.reset();
00940 }
00941 #endif
00942
00943 if (!LLApp::isExiting())
00944 {
00945
00946
00947
00948 if (gViewerWindow->mWindow->getVisible()
00949 && gViewerWindow->getActive()
00950 && !gViewerWindow->mWindow->getMinimized()
00951 && LLStartUp::getStartupState() == STATE_STARTED
00952 && !gViewerWindow->getShowProgress()
00953 && !gFocusMgr.focusLocked())
00954 {
00955 joystick->scanJoystick();
00956 gKeyboard->scanKeyboard();
00957 }
00958
00959
00960 {
00961 LLFastTimer t3(LLFastTimer::FTM_IDLE);
00962 idle();
00963
00964 {
00965 LLFastTimer t4(LLFastTimer::FTM_PUMP);
00966 gAres->process();
00967
00968 gServicePump->pump();
00969 gServicePump->callback();
00970 }
00971 }
00972
00973 if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
00974 {
00975 saveFinalSnapshot();
00976 disconnectViewer();
00977 }
00978
00979
00980 if (!LLApp::isExiting())
00981 {
00982 display();
00983
00984 LLFloaterSnapshot::update();
00985
00986 #if LL_WINDOWS && LL_LCD_COMPILE
00987
00988 gLcdScreen->UpdateDisplay();
00989 #endif
00990 }
00991
00992 }
00993
00994
00995 {
00996 LLFastTimer t2(LLFastTimer::FTM_SLEEP);
00997 bool run_multiple_threads = gSavedSettings.getBOOL("RunMultipleThreads");
00998
00999
01000 if(mYieldTime >= 0)
01001 {
01002 ms_sleep(mYieldTime);
01003 }
01004
01005
01006 if ( gNoRender
01007 || !gViewerWindow->mWindow->getVisible()
01008 || !gFocusMgr.getAppHasFocus())
01009 {
01010
01011 S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
01012
01013
01014 if (milliseconds_to_sleep > 0)
01015 {
01016 ms_sleep(milliseconds_to_sleep);
01017
01018 LLAppViewer::getTextureCache()->pause();
01019 LLAppViewer::getImageDecodeThread()->pause();
01020 }
01021 }
01022
01023 if (gRandomizeFramerate)
01024 {
01025 ms_sleep(rand() % 200);
01026 }
01027
01028 if (gPeriodicSlowFrame
01029 && (gFrameCount % 10 == 0))
01030 {
01031 llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
01032 ms_sleep(500);
01033 }
01034
01035
01036 const F64 min_frame_time = 0.0;
01037 const F64 min_idle_time = 0.0;
01038 const F64 max_idle_time = run_multiple_threads ? min_idle_time : llmin(.005*10.0*gFrameTimeSeconds, 0.005);
01039 idleTimer.reset();
01040 while(1)
01041 {
01042 S32 work_pending = 0;
01043 S32 io_pending = 0;
01044 work_pending += LLAppViewer::getTextureCache()->update(1);
01045 work_pending += LLAppViewer::getImageDecodeThread()->update(1);
01046 work_pending += LLAppViewer::getTextureFetch()->update(1);
01047 io_pending += LLVFSThread::updateClass(1);
01048 io_pending += LLLFSThread::updateClass(1);
01049 if (io_pending > 1000)
01050 {
01051 ms_sleep(llmin(io_pending/100,100));
01052 }
01053
01054 F64 frame_time = frameTimer.getElapsedTimeF64();
01055 F64 idle_time = idleTimer.getElapsedTimeF64();
01056 if (frame_time >= min_frame_time &&
01057 idle_time >= min_idle_time &&
01058 (!work_pending || idle_time >= max_idle_time))
01059 {
01060 break;
01061 }
01062 }
01063 frameTimer.reset();
01064
01065
01066
01067 if (run_multiple_threads == FALSE)
01068 {
01069 LLAppViewer::getTextureCache()->pause();
01070 LLAppViewer::getImageDecodeThread()->pause();
01071
01072 }
01073
01074
01075
01076 mMainloopTimeout->ping();
01077 }
01078
01079 }
01080 catch(std::bad_alloc)
01081 {
01082 llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
01083 }
01084 }
01085
01086
01087 if (STATE_STARTED == LLStartUp::getStartupState())
01088 {
01089 try
01090 {
01091 saveFinalSnapshot();
01092 }
01093 catch(std::bad_alloc)
01094 {
01095 llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
01096 }
01097 }
01098
01099 delete gServicePump;
01100
01101 mMainloopTimeout->stop();
01102
01103 llinfos << "Exiting main_loop" << llendflush;
01104
01105 return true;
01106 }
01107
01108 bool LLAppViewer::cleanup()
01109 {
01110
01111
01112 LLMortician::setZealous(TRUE);
01113
01114 LLVoiceClient::terminate();
01115
01116 disconnectViewer();
01117
01118 llinfos << "Viewer disconnected" << llendflush;
01119
01120 display_cleanup();
01121
01122 release_start_screen();
01123
01124 LLError::logToFixedBuffer(NULL);
01125
01126 llinfos << "Cleaning Up" << llendflush;
01127
01128 LLKeyframeDataCache::clear();
01129
01130
01131 LLHUDObject::cleanupHUDObjects();
01132 llinfos << "HUD Objects cleaned up" << llendflush;
01133
01134
01135 #if 0 // this seems to get us stuck in an infinite loop...
01136 gTransferManager.cleanup();
01137 #endif
01138
01139
01140
01141
01142 LLHUDManager::getInstance()->shutdownClass();
01143
01144
01145 delete gAssetStorage;
01146 gAssetStorage = NULL;
01147
01148 LLPolyMesh::freeAllMeshes();
01149
01150 delete gCacheName;
01151 gCacheName = NULL;
01152
01153
01154
01155 LLNotifyBox::cleanup();
01156
01157 LLWorldMap::getInstance()->reset();
01158
01159 llinfos << "Global stuff deleted" << llendflush;
01160
01161 #if !LL_RELEASE_FOR_DOWNLOAD
01162 if (gAudiop)
01163 {
01164 gAudiop->shutdown();
01165 }
01166 #else
01167
01168
01169 llwarns << "Hack, skipping audio engine cleanup" << llendflush;
01170 #endif
01171
01172
01173
01174
01175
01176
01177
01178 cleanupSavedSettings();
01179 llinfos << "Settings patched up" << llendflush;
01180
01181 delete gAudiop;
01182 gAudiop = NULL;
01183
01184
01185 removeCacheFiles("*.wav");
01186 removeCacheFiles("*.tmp");
01187 removeCacheFiles("*.lso");
01188 removeCacheFiles("*.out");
01189 removeCacheFiles("*.dsf");
01190 removeCacheFiles("*.bodypart");
01191 removeCacheFiles("*.clothing");
01192
01193 llinfos << "Cache files removed" << llendflush;
01194
01195
01196 cleanup_menus();
01197
01198
01199 while (1)
01200 {
01201 S32 pending = LLVFSThread::updateClass(0);
01202 pending += LLLFSThread::updateClass(0);
01203 if (!pending)
01204 {
01205 break;
01206 }
01207 llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
01208 ms_sleep(100);
01209 }
01210 llinfos << "Shutting down." << llendflush;
01211
01212
01213
01214
01215 delete gViewerWindow;
01216 gViewerWindow = NULL;
01217 llinfos << "ViewerWindow deleted" << llendflush;
01218
01219
01220 delete gKeyboard;
01221 gKeyboard = NULL;
01222
01223
01224
01225 LLSelectMgr::cleanupGlobals();
01226
01227 LLViewerObject::cleanupVOClasses();
01228
01229 LLWaterParamManager::cleanupClass();
01230 LLWLParamManager::cleanupClass();
01231 LLPostProcess::cleanupClass();
01232
01233 LLTracker::cleanupInstance();
01234
01235
01236
01237
01238
01239
01240
01241
01242 #if LL_WINDOWS && LL_LCD_COMPILE
01243
01244 delete gLcdScreen;
01245 gLcdScreen = NULL;
01246 #endif
01247
01248 LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
01249 if (!volume_manager->cleanup())
01250 {
01251 llwarns << "Remaining references in the volume manager!" << llendflush;
01252 }
01253 LLPrimitive::cleanupVolumeManager();
01254
01255 LLViewerParcelMgr::cleanupGlobals();
01256
01257
01258
01259
01260
01261 LLFollowCamMgr::cleanupClass();
01262
01263 LLPrimitive::cleanupVolumeManager();
01264 LLWorldMapView::cleanupClass();
01265 LLUI::cleanupClass();
01266
01267
01268
01269
01270
01271
01272 LLVFile::cleanupClass();
01273 llinfos << "VFS cleaned up" << llendflush;
01274
01275
01276 gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
01277
01278
01279
01280 gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
01281
01282
01283
01284 gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
01285 llinfos << "Saved settings" << llendflush;
01286
01287 std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
01288
01289 gCrashSettings.saveToFile(crash_settings_filename.c_str(), FALSE);
01290
01291 gSavedSettings.cleanup();
01292 gColors.cleanup();
01293 gCrashSettings.cleanup();
01294
01295
01296 LLURLHistory::saveFile("url_history.xml");
01297
01298
01299 LLMuteList::getInstance()->cache(gAgent.getID());
01300
01301 if (mPurgeOnExit)
01302 {
01303 llinfos << "Purging all cache files on exit" << llendflush;
01304 char mask[LL_MAX_PATH];
01305 snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str());
01306 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
01307 }
01308
01309 removeMarkerFile();
01310
01311 closeDebug();
01312
01313
01314 LLTimer idleTimer;
01315 idleTimer.reset();
01316 const F64 max_idle_time = 5.f;
01317 while(1)
01318 {
01319 S32 pending = 0;
01320 pending += LLAppViewer::getTextureCache()->update(1);
01321 pending += LLAppViewer::getImageDecodeThread()->update(1);
01322 pending += LLAppViewer::getTextureFetch()->update(1);
01323 pending += LLVFSThread::updateClass(0);
01324 pending += LLLFSThread::updateClass(0);
01325 F64 idle_time = idleTimer.getElapsedTimeF64();
01326 if (!pending || idle_time >= max_idle_time)
01327 {
01328 llwarns << "Quitting with pending background tasks." << llendl;
01329 break;
01330 }
01331 }
01332
01333
01334
01335 sTextureCache->shutdown();
01336 sTextureFetch->shutdown();
01337 sImageDecodeThread->shutdown();
01338 delete sTextureCache;
01339 sTextureCache = NULL;
01340 delete sTextureFetch;
01341 sTextureFetch = NULL;
01342 delete sImageDecodeThread;
01343 sImageDecodeThread = NULL;
01344
01345 gImageList.shutdown();
01346
01347
01348 LLImageJ2C::closeDSO();
01349 LLImageFormatted::cleanupClass();
01350 LLVFSThread::cleanupClass();
01351 LLLFSThread::cleanupClass();
01352
01353 llinfos << "VFS Thread finished" << llendflush;
01354
01355 #ifndef LL_RELEASE_FOR_DOWNLOAD
01356 llinfos << "Auditing VFS" << llendl;
01357 gVFS->audit();
01358 #endif
01359
01360
01361
01362 delete gStaticVFS;
01363 gStaticVFS = NULL;
01364 delete gVFS;
01365 gVFS = NULL;
01366
01367 LLWatchdog::getInstance()->cleanup();
01368
01369 end_messaging_system();
01370
01371
01372 LLCurl::cleanupClass();
01373
01374
01375
01376 if (!gLaunchFileOnQuit.empty())
01377 {
01378 #if LL_WINDOWS
01379
01380 SetCursor(LoadCursor(NULL, IDC_WAIT));
01381 #endif
01382
01383
01384 ms_sleep(1000);
01385
01386 LLWeb::loadURLExternal( gLaunchFileOnQuit );
01387 }
01388
01389
01390 llinfos << "Goodbye" << llendflush;
01391
01392 return true;
01393 }
01394
01395 bool LLAppViewer::initThreads()
01396 {
01397 #if MEM_TRACK_MEM
01398 static const bool enable_threads = false;
01399 #else
01400 static const bool enable_threads = true;
01401 #endif
01402
01403 LLWatchdog::getInstance()->init();
01404
01405 LLVFSThread::initClass(enable_threads && true);
01406 LLLFSThread::initClass(enable_threads && true);
01407
01408
01409 LLAppViewer::sImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true);
01410 LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
01411 LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), enable_threads && false);
01412 LLImageWorker::initClass(LLAppViewer::getImageDecodeThread());
01413 LLImageJ2C::openDSO();
01414
01415
01416 return true;
01417 }
01418
01419 void errorCallback(const std::string &error_string)
01420 {
01421 #ifndef LL_RELEASE_FOR_DOWNLOAD
01422 OSMessageBox(error_string.c_str(), "Fatal Error", OSMB_OK);
01423 #endif
01424
01425
01426 gLLErrorActivated = true;
01427
01428 LLError::crashAndLoop(error_string);
01429 }
01430
01431 bool LLAppViewer::initLogging()
01432 {
01433
01434
01435
01436 LLError::initForApplication(
01437 gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
01438 LLError::setFatalFunction(errorCallback);
01439
01440
01441 std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
01442 "SecondLife.old");
01443 LLFile::remove(old_log_file.c_str());
01444
01445
01446 std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
01447 "SecondLife.log");
01448 LLFile::rename(log_file.c_str(), old_log_file.c_str());
01449
01450
01451
01452 LLError::logToFile(log_file);
01453
01454
01455 return true;
01456 }
01457
01458 void LLAppViewer::loadSettingsFromDirectory(ELLPath path_index)
01459 {
01460 for(LLSD::map_iterator itr = mSettingsFileList.beginMap(); itr != mSettingsFileList.endMap(); ++itr)
01461 {
01462 LLString settings_name = (*itr).first;
01463 LLString settings_file = mSettingsFileList[settings_name].asString();
01464
01465 LLString full_settings_path = gDirUtilp->getExpandedFilename(path_index, settings_file);
01466
01467 if(settings_name == sGlobalSettingsName
01468 && path_index == LL_PATH_USER_SETTINGS)
01469 {
01470
01471
01472
01473
01474 std::string custom_path;
01475 if(gSettings[sGlobalSettingsName]->controlExists("ClientSettingsFile"))
01476 {
01477 custom_path =
01478 gSettings[sGlobalSettingsName]->getString("ClientSettingsFile");
01479 }
01480 if(!custom_path.empty())
01481 {
01482 full_settings_path = custom_path;
01483 }
01484 }
01485
01486 if(gSettings.find(settings_name) == gSettings.end())
01487 {
01488 llwarns << "Cannot load " << settings_file << " - No matching settings group for name " << settings_name << llendl;
01489 continue;
01490 }
01491 if(!gSettings[settings_name]->loadFromFile(full_settings_path))
01492 {
01493 llwarns << "Cannot load " << full_settings_path << " - No settings found." << llendl;
01494 }
01495 else
01496 {
01497 llinfos << "Loaded settings file " << full_settings_path << llendl;
01498 }
01499 }
01500 }
01501
01502 std::string LLAppViewer::getSettingsFileName(const std::string& file)
01503 {
01504 if(mSettingsFileList.has(file))
01505 {
01506 return mSettingsFileList[file].asString();
01507 }
01508 return std::string();
01509 }
01510
01511 bool LLAppViewer::initConfiguration()
01512 {
01513
01514 gSettings[sGlobalSettingsName] = &gSavedSettings;
01515 gSettings[sPerAccountSettingsName] = &gSavedPerAccountSettings;
01516 gSettings[sCrashSettingsName] = &gCrashSettings;
01517
01518
01519 std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
01520 LLControlGroup settings_control;
01521 llinfos << "Loading settings file list" << settings_file_list << llendl;
01522 if (0 == settings_control.loadFromFile(settings_file_list))
01523 {
01524 llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
01525 }
01526
01527 mSettingsFileList = settings_control.getLLSD("Files");
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540 loadSettingsFromDirectory(LL_PATH_APP_SETTINGS);
01541
01542
01543 gSavedSettings.setString("ClientSettingsFile",
01544 gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFileName("Global")));
01545
01546 gSavedSettings.setString("VersionChannelName", LL_CHANNEL);
01547
01548 #ifndef LL_RELEASE_FOR_DOWNLOAD
01549 gSavedSettings.setBOOL("ShowConsoleWindow", TRUE);
01550 gSavedSettings.setBOOL("AllowMultipleViewers", TRUE);
01551 #endif
01552
01553 #if !LL_DYNAMIC_FONT_DISCOVERY
01554
01555 gSavedSettings.setString("FontSansSerifFallback",
01556 LLWindow::getFontListSans());
01557 #endif
01558
01559
01560
01561
01562 LLFirstUse::addConfigVariable("FirstBalanceIncrease");
01563 LLFirstUse::addConfigVariable("FirstBalanceDecrease");
01564 LLFirstUse::addConfigVariable("FirstSit");
01565 LLFirstUse::addConfigVariable("FirstMap");
01566 LLFirstUse::addConfigVariable("FirstGoTo");
01567 LLFirstUse::addConfigVariable("FirstBuild");
01568 LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
01569 LLFirstUse::addConfigVariable("FirstTeleport");
01570 LLFirstUse::addConfigVariable("FirstOverrideKeys");
01571 LLFirstUse::addConfigVariable("FirstAttach");
01572 LLFirstUse::addConfigVariable("FirstAppearance");
01573 LLFirstUse::addConfigVariable("FirstInventory");
01574 LLFirstUse::addConfigVariable("FirstSandbox");
01575 LLFirstUse::addConfigVariable("FirstFlexible");
01576 LLFirstUse::addConfigVariable("FirstDebugMenus");
01577 LLFirstUse::addConfigVariable("FirstStreamingMusic");
01578 LLFirstUse::addConfigVariable("FirstStreamingVideo");
01579 LLFirstUse::addConfigVariable("FirstSculptedPrim");
01580 LLFirstUse::addConfigVariable("FirstVoice");
01581 LLFirstUse::addConfigVariable("FirstMedia");
01582
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 LLUICtrlFactory::getInstance();
01596
01597
01598
01599
01600 LLAlertDialog::parseAlerts("alerts.xml", &gSavedSettings, TRUE);
01601
01602 #if LL_DYNAMIC_FONT_DISCOVERY
01603
01604
01605
01606
01607 gSavedSettings.setString("FontSansSerifFallback",
01608 LLWindow::getFontListSans());
01609 #endif
01610
01611
01612 LLControlGroupCLP clp;
01613 std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
01614 "cmd_line.xml");
01615 clp.configure(cmd_line_config, &gSavedSettings);
01616
01617 if(!initParseCommandLine(clp))
01618 {
01619 llwarns
01620 << "Error parsing command line options. Command Line options ignored."
01621 << llendl;
01622
01623 llinfos << "Command line usage:\n" << clp << llendl;
01624
01625 std::ostringstream msg;
01626 msg << "Second Life found an error parsing the command line. \n"
01627 << "Please see: http://wiki.secondlife.com/wiki/Client_parameters \n"
01628 << "Error: " << clp.getErrorMessage();
01629
01630 OSMessageBox(
01631 msg.str().c_str(),
01632 NULL,
01633 OSMB_OK);
01634
01635 return false;
01636 }
01637
01638
01639
01640
01641
01642 if(clp.hasOption("settings"))
01643 {
01644 std::string user_settings_filename =
01645 gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
01646 clp.getOption("settings")[0]);
01647 gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
01648 llinfos << "Using command line specified settings filename: "
01649 << user_settings_filename << llendl;
01650 }
01651
01652
01653 loadSettingsFromDirectory(LL_PATH_USER_SETTINGS);
01654
01655
01656 clp.notify();
01657
01658
01659
01660 if (gSavedSettings.getBOOL("ShowConsoleWindow"))
01661 {
01662 initConsole();
01663 }
01664
01665 if(clp.hasOption("help"))
01666 {
01667 std::ostringstream msg;
01668 msg << "Command line usage:\n" << clp;
01669 llinfos << msg.str() << llendl;
01670
01671 OSMessageBox(
01672 msg.str().c_str(),
01673 NULL,
01674 OSMB_OK);
01675
01676 return false;
01677 }
01678
01680
01681 if(clp.hasOption("setdefault"))
01682 {
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707 }
01708
01709 if(clp.hasOption("set"))
01710 {
01711 const LLCommandLineParser::token_vector_t& set_values = clp.getOption("set");
01712 if(0x1 & set_values.size())
01713 {
01714 llwarns << "Invalid '--set' parameter count." << llendl;
01715 }
01716 else
01717 {
01718 LLCommandLineParser::token_vector_t::const_iterator itr = set_values.begin();
01719 for(; itr != set_values.end(); ++itr)
01720 {
01721 const std::string& name = *itr;
01722 const std::string& value = *(++itr);
01723 LLControlVariable* c = gSettings[sGlobalSettingsName]->getControl(name);
01724 if(c)
01725 {
01726 c->setValue(value, false);
01727 }
01728 else
01729 {
01730 llwarns << "'--set' specified with unknown setting: '"
01731 << name << "'." << llendl;
01732 }
01733 }
01734 }
01735 }
01736
01737 initGridChoice();
01738
01739
01740 if(clp.hasOption("crashonstartup"))
01741 {
01742 gCrashOnStartup = TRUE;
01743 }
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762 if(clp.hasOption("url"))
01763 {
01764 std::string slurl = clp.getOption("url")[0];
01765 if (LLURLDispatcher::isSLURLCommand(slurl))
01766 {
01767 LLStartUp::sSLURLCommand = slurl;
01768 }
01769 else
01770 {
01771 LLURLSimString::setString(slurl);
01772 }
01773 }
01774 else if(clp.hasOption("slurl"))
01775 {
01776 std::string slurl = clp.getOption("slurl")[0];
01777 if(LLURLDispatcher::isSLURL(slurl))
01778 {
01779 if (LLURLDispatcher::isSLURLCommand(slurl))
01780 {
01781 LLStartUp::sSLURLCommand = slurl;
01782 }
01783 else
01784 {
01785 LLURLSimString::setString(slurl);
01786 }
01787 }
01788 }
01789
01790 const LLControlVariable* loginuri = gSavedSettings.getControl("LoginURI");
01791 if(loginuri && LLString::null != loginuri->getValue().asString())
01792 {
01793 addLoginURI(loginuri->getValue().asString());
01794 }
01795
01796 const LLControlVariable* helperuri = gSavedSettings.getControl("HelperURI");
01797 if(helperuri && LLString::null != helperuri->getValue().asString())
01798 {
01799 setHelperURI(helperuri->getValue().asString());
01800 }
01801
01802 const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinFolder");
01803 if(skinfolder && LLString::null != skinfolder->getValue().asString())
01804 {
01805 gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
01806 }
01807
01808 mYieldTime = gSavedSettings.getS32("YieldTime");
01809
01810
01811 gSecondLife = "Second Life";
01812
01813
01814 if (! gDirUtilp->getSkinDir().empty() )
01815 {
01816 std::string skin_def_file = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, "skin.xml");
01817 LLXmlTree skin_def_tree;
01818
01819 if (!skin_def_tree.parseFile(skin_def_file))
01820 {
01821 llerrs << "Failed to parse skin definition." << llendl;
01822 }
01823
01824 LLXmlTreeNode* rootp = skin_def_tree.getRoot();
01825 LLXmlTreeNode* disabled_message_node = rootp->getChildByName("disabled_message");
01826 if (disabled_message_node)
01827 {
01828 gDisabledMessage = disabled_message_node->getContents();
01829 }
01830
01831 static LLStdStringHandle hide_links_string = LLXmlTree::addAttributeString("hide_links");
01832 rootp->getFastAttributeBOOL(hide_links_string, gHideLinks);
01833
01834
01835
01836 static LLStdStringHandle silent_string = LLXmlTree::addAttributeString("silent_update");
01837 BOOL silent_update;
01838 rootp->getFastAttributeBOOL(silent_string, silent_update);
01839 gHideLinks = (gHideLinks || silent_update);
01840 }
01841
01842 #if LL_DARWIN
01843
01844 init_apple_menu(gSecondLife.c_str());
01845
01846 #if __ppc__
01847
01848
01849 if(!gSysCPU.hasAltivec())
01850 {
01851 std::ostringstream msg;
01852 msg << gSecondLife << " requires a processor with AltiVec (G4 or later).";
01853 OSMessageBox(
01854 msg.str().c_str(),
01855 NULL,
01856 OSMB_OK);
01857 removeMarkerFile();
01858 return false;
01859 }
01860 #endif
01861
01862 #endif // LL_DARWIN
01863
01864
01865
01866 std::ostringstream splash_msg;
01867 splash_msg << "Loading " << gSecondLife << "...";
01868 LLSplashScreen::show();
01869 LLSplashScreen::update(splash_msg.str().c_str());
01870
01871
01872 LLVolumeMgr* volume_manager = new LLVolumeMgr();
01873 volume_manager->useMutex();
01874 LLPrimitive::setVolumeManager(volume_manager);
01875
01876
01877
01878 gStartTime = totalTime();
01879
01880
01881
01882
01883 #if LL_RELEASE_FOR_DOWNLOAD
01884 gWindowTitle = gSecondLife;
01885 #elif LL_DEBUG
01886 gWindowTitle = gSecondLife + LLString(" [DEBUG] ") + gArgs;
01887 #else
01888 gWindowTitle = gSecondLife + LLString(" ") + gArgs;
01889 #endif
01890 LLString::truncate(gWindowTitle, 255);
01891
01892
01893
01894
01895
01896 std::string slurl;
01897 if (!LLStartUp::sSLURLCommand.empty())
01898 {
01899 slurl = LLStartUp::sSLURLCommand;
01900 }
01901 else if (LLURLSimString::parse())
01902 {
01903 slurl = LLURLSimString::getURL();
01904 }
01905 if (!slurl.empty())
01906 {
01907 if (send_url_to_other_instance(slurl))
01908 {
01909
01910 return false;
01911 }
01912 }
01913
01914 if (!gSavedSettings.getBOOL("AllowMultipleViewers"))
01915 {
01916
01917
01918
01919
01920 mSecondInstance = anotherInstanceRunning();
01921
01922 if (mSecondInstance)
01923 {
01924 std::ostringstream msg;
01925 msg <<
01926 gSecondLife << " is already running.\n"
01927 "\n"
01928 "Check your task bar for a minimized copy of the program.\n"
01929 "If this message persists, restart your computer.",
01930 OSMessageBox(
01931 msg.str().c_str(),
01932 NULL,
01933 OSMB_OK);
01934 return false;
01935 }
01936
01937 initMarkerFile();
01938
01939 #if LL_SEND_CRASH_REPORTS
01940 if (gLastExecEvent == LAST_EXEC_FROZE)
01941 {
01942 llinfos << "Last execution froze, requesting to send crash report." << llendl;
01943
01944
01945
01946 std::ostringstream msg;
01947 msg << gSecondLife
01948 << " appears to have frozen or crashed on the previous run.\n"
01949 << "Would you like to send a crash report?";
01950 std::string alert;
01951 alert = gSecondLife;
01952 alert += " Alert";
01953 S32 choice = OSMessageBox(msg.str().c_str(),
01954 alert.c_str(),
01955 OSMB_YESNO);
01956 if (OSBTN_YES == choice)
01957 {
01958 llinfos << "Sending crash report." << llendl;
01959
01960 #if LL_WINDOWS
01961 std::string exe_path = gDirUtilp->getAppRODataDir();
01962 exe_path += gDirUtilp->getDirDelimiter();
01963 exe_path += "win_crash_logger.exe";
01964
01965 std::string arg_string = "-previous ";
01966
01967
01968 _spawnl(_P_WAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
01969 #elif LL_DARWIN
01970 std::string command_str;
01971 command_str = "crashreporter.app/Contents/MacOS/crashreporter ";
01972 command_str += "-previous";
01973
01974
01975 system(command_str.c_str());
01976 #elif LL_LINUX || LL_SOLARIS
01977 std::string cmd =gDirUtilp->getAppRODataDir();
01978 cmd += gDirUtilp->getDirDelimiter();
01979 #if LL_LINUX
01980 cmd += "linux-crash-logger.bin";
01981 #else // LL_SOLARIS
01982 cmd += "bin/solaris-crash-logger";
01983 #endif
01984 char* const cmdargv[] =
01985 {(char*)cmd.c_str(),
01986 (char*)"-previous",
01987 NULL};
01988 pid_t pid = fork();
01989 if (pid == 0)
01990 {
01991 execv(cmd.c_str(), cmdargv);
01992 llwarns << "execv failure when trying to start " << cmd << llendl;
01993 _exit(1);
01994 } else {
01995 if (pid > 0)
01996 {
01997
01998 int childExitStatus;
01999 waitpid(pid, &childExitStatus, 0);
02000 } else {
02001 llwarns << "fork failure." << llendl;
02002 }
02003 }
02004 #endif
02005 }
02006 else
02007 {
02008 llinfos << "Not sending crash report." << llendl;
02009 }
02010 }
02011 #endif // #if LL_SEND_CRASH_REPORTS
02012 }
02013 else
02014 {
02015 mSecondInstance = anotherInstanceRunning();
02016
02017 if (mSecondInstance)
02018 {
02019
02020
02021 LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
02022 if(disable_voice)
02023 {
02024 const BOOL DO_NOT_PERSIST = FALSE;
02025 disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
02026 }
02027 }
02028
02029 initMarkerFile();
02030 }
02031
02032
02033 LLString nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
02034 if ( nextLoginLocation.length() )
02035 {
02036 LLURLSimString::setString( nextLoginLocation.c_str() );
02037 };
02038
02039 gLastRunVersion = gSavedSettings.getString("LastRunVersion");
02040
02041 return true;
02042 }
02043
02044 bool LLAppViewer::initWindow()
02045 {
02046 LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
02047
02048
02049 gNoRender = gSavedSettings.getBOOL("DisableRendering");
02050
02051
02052 LLSplashScreen::hide();
02053
02054
02055 char window_title_str[256];
02056 strncpy(window_title_str, gWindowTitle.c_str(), sizeof(window_title_str) - 1);
02057 window_title_str[sizeof(window_title_str) - 1] = '\0';
02058
02059
02060 BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
02061 gViewerWindow = new LLViewerWindow(window_title_str, "Second Life",
02062 gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
02063 gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
02064 FALSE, ignorePixelDepth);
02065
02066 if (gSavedSettings.getBOOL("FullScreen"))
02067 {
02068 gViewerWindow->toggleFullscreen(FALSE);
02069
02070 }
02071
02072 if (gSavedSettings.getBOOL("WindowMaximized"))
02073 {
02074 gViewerWindow->mWindow->maximize();
02075 gViewerWindow->getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
02076 }
02077
02078 if (!gNoRender)
02079 {
02080
02081
02082
02083
02084
02085 gSavedSettings.setBOOL("RenderInitError", TRUE);
02086 gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
02087
02088 gPipeline.init();
02089 stop_glerror();
02090 gViewerWindow->initGLDefaults();
02091
02092 gSavedSettings.setBOOL("RenderInitError", FALSE);
02093 gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
02094 }
02095
02096
02097 if(gCrashOnStartup)
02098 {
02099 LLAppViewer::instance()->forceErrorLLError();
02100 }
02101
02102 LLUI::sWindow = gViewerWindow->getWindow();
02103
02104 LLAlertDialog::parseAlerts("alerts.xml");
02105 LLNotifyBox::parseNotify("notify.xml");
02106 LLTrans::parseStrings("strings.xml");
02107
02108
02109 gViewerWindow->setCursor(UI_CURSOR_WAIT);
02110
02111
02112 gViewerWindow->initBase();
02113
02114
02115 gViewerWindow->mWindow->show();
02116
02117
02118 return true;
02119 }
02120
02121 void LLAppViewer::closeDebug()
02122 {
02123 std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
02124 llinfos << "Opening debug file " << debug_filename << llendl;
02125 std::ofstream out_file(debug_filename.c_str());
02126 LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
02127 out_file.close();
02128 }
02129
02130 void LLAppViewer::cleanupSavedSettings()
02131 {
02132 gSavedSettings.setBOOL("MouseSun", FALSE);
02133
02134 gSavedSettings.setBOOL("FlyBtnState", FALSE);
02135
02136 gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
02137 gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
02138 gSavedSettings.setBOOL("BuildBtnState", FALSE);
02139
02140 gSavedSettings.setBOOL("UseEnergy", TRUE);
02141
02142 gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
02143
02144 gSavedSettings.setBOOL("AllowIdleAFK", gAllowIdleAFK);
02145 gSavedSettings.setBOOL("AllowTapTapHoldRun", gAllowTapTapHoldRun);
02146 gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
02147
02148 if (!gNoRender)
02149 {
02150 if (gDebugView)
02151 {
02152 gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
02153 gSavedSettings.setBOOL("ShowDebugStats", gDebugView->mFloaterStatsp->getVisible());
02154 }
02155 }
02156
02157
02158
02159 BOOL fullscreen = gViewerWindow->mWindow->getFullscreen();
02160 BOOL maximized = gViewerWindow->mWindow->getMaximized();
02161 if (!fullscreen && !maximized)
02162 {
02163 LLCoordScreen window_pos;
02164
02165 if (gViewerWindow->mWindow->getPosition(&window_pos))
02166 {
02167 gSavedSettings.setS32("WindowX", window_pos.mX);
02168 gSavedSettings.setS32("WindowY", window_pos.mY);
02169 }
02170 }
02171
02172 gSavedSettings.setF32("MapScale", gMapScale );
02173 gSavedSettings.setF32("MiniMapScale", gMiniMapScale );
02174 gSavedSettings.setBOOL("AsyncKeyboard", gHandleKeysAsync);
02175 gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips);
02176
02177
02178 if (gAgent.mInitialized)
02179 {
02180 gSavedSettings.setF32("RenderFarClip", gAgent.mDrawDistance);
02181 }
02182
02183
02184
02185
02186 }
02187
02188 void LLAppViewer::removeCacheFiles(const char* file_mask)
02189 {
02190 char mask[LL_MAX_PATH];
02191 snprintf(mask, LL_MAX_PATH, "%s%s", gDirUtilp->getDirDelimiter().c_str(), file_mask);
02192 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "").c_str(), mask);
02193 }
02194
02195 void LLAppViewer::writeSystemInfo()
02196 {
02197 gDebugInfo["SLLog"] = LLError::logFileName();
02198
02199 gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
02200 gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
02201 gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
02202 gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
02203 gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
02204
02205 gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
02206 gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
02207 gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMhz();
02208 gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
02209 gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
02210 gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
02211
02212 gDebugInfo["RAMInfo"] = llformat("%u", gSysMemory.getPhysicalMemoryKB());
02213 gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
02214
02215
02216 LL_INFOS("SystemInfo") << gSecondLife
02217 << " version " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH
02218 << LL_ENDL;
02219
02220
02221 time_t now;
02222 time(&now);
02223 char tbuffer[256];
02224 strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
02225 LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL;
02226
02227
02228 LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL;
02229 LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL;
02230 LL_INFOS("SystemInfo") << "OS: " << getOSInfo().getOSStringSimple() << LL_ENDL;
02231 LL_INFOS("SystemInfo") << "OS info: " << getOSInfo() << LL_ENDL;
02232 }
02233
02234 void LLAppViewer::handleSyncViewerCrash()
02235 {
02236 LLAppViewer* pApp = LLAppViewer::instance();
02237
02238 pApp->handleSyncCrashTrace();
02239 }
02240
02241 void LLAppViewer::handleViewerCrash()
02242 {
02243 llinfos << "Handle viewer crash entry." << llendl;
02244
02245 LLAppViewer* pApp = LLAppViewer::instance();
02246 if (pApp->beingDebugged())
02247 {
02248
02249 abort();
02250 }
02251
02252
02253
02254 if (pApp->mReportedCrash)
02255 {
02256 return;
02257 }
02258 pApp->mReportedCrash = TRUE;
02259
02260
02261
02262 gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
02263
02264 gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
02265 gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
02266 gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
02267 gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
02268
02269 LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
02270 if ( parcel && parcel->getMusicURL()[0])
02271 {
02272 gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
02273 }
02274 if ( parcel && parcel->getMediaURL()[0])
02275 {
02276 gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
02277 }
02278
02279
02280 gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
02281 gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
02282 gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName().c_str();
02283 gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath().c_str();
02284 if(gLogoutInProgress)
02285 {
02286 gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
02287 }
02288 else
02289 {
02290 gDebugInfo["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
02291 }
02292
02293 if(gAgent.getRegion())
02294 {
02295 gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
02296 gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
02297 }
02298
02299
02300
02301
02302 if (gDirUtilp)
02303 {
02304 LLString crash_file_name;
02305 if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME);
02306 else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME);
02307 llinfos << "Creating crash marker file " << crash_file_name << llendl;
02308 apr_file_t* crash_file = ll_apr_file_open(crash_file_name, LL_APR_W);
02309 if (crash_file)
02310 {
02311 LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL;
02312 }
02313 else
02314 {
02315 LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL;
02316 }
02317 apr_file_close(crash_file);
02318 }
02319
02320 if (gMessageSystem && gDirUtilp)
02321 {
02322 std::string filename;
02323 filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "stats.log");
02324 llofstream file(filename.c_str(), llofstream::binary);
02325 if(file.good())
02326 {
02327 llinfos << "Handle viewer crash generating stats log." << llendl;
02328 gMessageSystem->summarizeLogs(file);
02329 file.close();
02330 }
02331 }
02332
02333 if (gMessageSystem)
02334 {
02335 gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
02336 gMessageSystem->stopLogging();
02337 }
02338
02339 LLWorld::getInstance()->getInfo(gDebugInfo);
02340
02341
02342 pApp->closeDebug();
02343
02344 LLError::logToFile("");
02345
02346
02347 if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
02348 {
02349 pApp->removeMarkerFile(true);
02350 }
02351 else
02352 {
02353 pApp->removeMarkerFile(false);
02354 }
02355
02356
02357 pApp->handleCrashReporting();
02358
02359 return;
02360 }
02361
02362 void LLAppViewer::setCrashBehavior(S32 cb)
02363 {
02364 mCrashBehavior = cb;
02365 gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, mCrashBehavior);
02366 }
02367
02368 bool LLAppViewer::anotherInstanceRunning()
02369 {
02370
02371
02372
02373 std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME);
02374 LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
02375
02376
02377 apr_file_t* fMarker = ll_apr_file_open(marker_file, LL_APR_RB);
02378 if (fMarker != NULL)
02379 {
02380
02381 apr_file_close(fMarker);
02382 fMarker = ll_apr_file_open(marker_file, LL_APR_WB);
02383 if (fMarker == NULL)
02384 {
02385
02386 LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
02387 return TRUE;
02388 }
02389 if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)
02390 {
02391 apr_file_close(fMarker);
02392 LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
02393 return TRUE;
02394 }
02395
02396 apr_file_close(fMarker);
02397 }
02398 LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL;
02399 return FALSE;
02400 }
02401
02402 void LLAppViewer::initMarkerFile()
02403 {
02404
02405
02406
02407
02408 mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
02409 LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419 LLString logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
02420 LLString llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
02421 LLString error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
02422
02423 apr_file_t* fMarker = ll_apr_file_open(logout_marker_file, LL_APR_RB);
02424 if(fMarker != NULL)
02425 {
02426 apr_file_close(fMarker);
02427 LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << LL_ENDL;
02428 gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
02429 }
02430 fMarker = ll_apr_file_open(llerror_marker_file, LL_APR_RB);
02431 if(fMarker != NULL)
02432 {
02433 apr_file_close(fMarker);
02434 llinfos << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << llendl;
02435 if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
02436 else gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
02437 }
02438 fMarker = ll_apr_file_open(error_marker_file, LL_APR_RB);
02439 if(fMarker != NULL)
02440 {
02441 apr_file_close(fMarker);
02442 LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << LAST_EXEC_OTHER_CRASH << LL_ENDL;
02443 if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
02444 else gLastExecEvent = LAST_EXEC_OTHER_CRASH;
02445 }
02446
02447 ll_apr_file_remove(logout_marker_file);
02448 ll_apr_file_remove(llerror_marker_file);
02449 ll_apr_file_remove(error_marker_file);
02450
02451
02452 if(anotherInstanceRunning())
02453 {
02454 return;
02455 }
02456
02457 fMarker = ll_apr_file_open(mMarkerFileName, LL_APR_RB);
02458 if (fMarker != NULL)
02459 {
02460 apr_file_close(fMarker);
02461 gLastExecEvent = LAST_EXEC_FROZE;
02462 LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL;
02463 }
02464
02465
02466 mMarkerFile = ll_apr_file_open(mMarkerFileName, LL_APR_W);
02467 if (mMarkerFile)
02468 {
02469 LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL;
02470 }
02471 else
02472 {
02473 LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL;
02474 return;
02475 }
02476 if (apr_file_lock(mMarkerFile, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)
02477 {
02478 apr_file_close(mMarkerFile);
02479 LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL;
02480 return;
02481 }
02482
02483 LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL;
02484 }
02485
02486 void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
02487 {
02488 LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL;
02489 if (mMarkerFile != NULL)
02490 {
02491 ll_apr_file_remove( mMarkerFileName );
02492 mMarkerFile = NULL;
02493 }
02494 if (mLogoutMarkerFile != NULL && !leave_logout_marker)
02495 {
02496 ll_apr_file_remove( mLogoutMarkerFileName );
02497 mLogoutMarkerFile = NULL;
02498 }
02499 }
02500
02501 void LLAppViewer::forceQuit()
02502 {
02503 LLApp::setQuitting();
02504 }
02505
02506 void LLAppViewer::requestQuit()
02507 {
02508 llinfos << "requestQuit" << llendl;
02509
02510 LLViewerRegion* region = gAgent.getRegion();
02511
02512 if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
02513 {
02514
02515 forceQuit();
02516 return;
02517 }
02518
02519 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
02520 effectp->setPositionGlobal(gAgent.getPositionGlobal());
02521 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
02522 LLHUDManager::getInstance()->sendEffects();
02523
02524
02525
02526 if (gFloaterView)
02527 {
02528
02529 gFloaterView->closeAllChildren(true);
02530 }
02531
02532 send_stats();
02533
02534 gLogoutTimer.reset();
02535 mQuitRequested = true;
02536 }
02537
02538 static void finish_quit(S32 option, void *userdata)
02539 {
02540 if (option == 0)
02541 {
02542 LLAppViewer::instance()->requestQuit();
02543 }
02544 }
02545
02546 void LLAppViewer::userQuit()
02547 {
02548 gViewerWindow->alertXml("ConfirmQuit", finish_quit, NULL);
02549 }
02550
02551 static void finish_early_exit(S32 option, void* userdata)
02552 {
02553 LLAppViewer::instance()->forceQuit();
02554 }
02555
02556 void LLAppViewer::earlyExit(const LLString& msg)
02557 {
02558 llwarns << "app_early_exit: " << msg << llendl;
02559 gDoDisconnect = TRUE;
02560
02561
02562
02563 LLAlertDialog::showCritical(msg, finish_early_exit, NULL);
02564 }
02565
02566 void LLAppViewer::forceExit(S32 arg)
02567 {
02568 removeMarkerFile();
02569
02570
02571 exit(arg);
02572 }
02573
02574 void LLAppViewer::abortQuit()
02575 {
02576 llinfos << "abortQuit()" << llendl;
02577 mQuitRequested = false;
02578 }
02579
02580 bool LLAppViewer::initCache()
02581 {
02582 mPurgeCache = false;
02583
02584 if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
02585 gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
02586 {
02587 gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
02588 mPurgeCache = true;
02589 }
02590
02591 else
02592 {
02593 static const S32 cache_version = 5;
02594 if (gSavedSettings.getS32("LocalCacheVersion") != cache_version)
02595 {
02596 mPurgeCache = true;
02597 gSavedSettings.setS32("LocalCacheVersion", cache_version);
02598 }
02599 }
02600
02601
02602 LLString cache_location = gSavedSettings.getString("CacheLocation");
02603 LLString new_cache_location = gSavedSettings.getString("NewCacheLocation");
02604 if (new_cache_location != cache_location)
02605 {
02606 gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
02607 purgeCache();
02608 gSavedSettings.setString("CacheLocation", new_cache_location);
02609 }
02610
02611 if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
02612 {
02613 LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL;
02614 gSavedSettings.setString("CacheLocation", "");
02615 }
02616
02617 if (mPurgeCache)
02618 {
02619 LLSplashScreen::update("Clearing cache...");
02620 purgeCache();
02621 }
02622
02623 LLSplashScreen::update("Initializing Texture Cache...");
02624
02625
02626
02627 BOOL read_only = mSecondInstance ? true : false;
02628 const S32 MB = 1024*1024;
02629 S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
02630 const S64 MAX_CACHE_SIZE = 1024*MB;
02631 cache_size = llmin(cache_size, MAX_CACHE_SIZE);
02632 S64 texture_cache_size = ((cache_size * 8)/10);
02633 S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, read_only);
02634 texture_cache_size -= extra;
02635
02636 LLSplashScreen::update("Initializing VFS...");
02637
02638
02639 S64 vfs_size = cache_size - texture_cache_size;
02640 const S64 MAX_VFS_SIZE = 1024 * MB;
02641 vfs_size = llmin(vfs_size, MAX_VFS_SIZE);
02642 vfs_size = (vfs_size / MB) * MB;
02643 U32 vfs_size_u32 = (U32)vfs_size;
02644 U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
02645 bool resize_vfs = (vfs_size_u32 != old_vfs_size);
02646 if (resize_vfs)
02647 {
02648 gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB);
02649 }
02650 LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << LL_ENDL;
02651
02652
02653
02654 srand(time(NULL));
02655 U32 old_salt = gSavedSettings.getU32("VFSSalt");
02656 U32 new_salt;
02657 char old_vfs_data_file[LL_MAX_PATH];
02658 char old_vfs_index_file[LL_MAX_PATH];
02659 char new_vfs_data_file[LL_MAX_PATH];
02660 char new_vfs_index_file[LL_MAX_PATH];
02661 char static_vfs_index_file[LL_MAX_PATH];
02662 char static_vfs_data_file[LL_MAX_PATH];
02663
02664 if (gSavedSettings.getBOOL("AllowMultipleViewers"))
02665 {
02666
02667 new_salt = old_salt;
02668 }
02669 else
02670 {
02671 do
02672 {
02673 new_salt = rand();
02674 } while( new_salt == old_salt );
02675 }
02676
02677 snprintf(old_vfs_data_file, LL_MAX_PATH, "%s%u",
02678 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE).c_str(),
02679 old_salt);
02680
02681
02682 llstat s;
02683 S32 stat_result = LLFile::stat(old_vfs_data_file, &s);
02684 if (stat_result)
02685 {
02686
02687 std::string mask;
02688 mask = gDirUtilp->getDirDelimiter();
02689 mask += VFS_DATA_FILE_BASE;
02690 mask += "*";
02691
02692 std::string dir;
02693 dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
02694
02695 std::string found_file;
02696 if (gDirUtilp->getNextFileInDir(dir, mask, found_file, false))
02697 {
02698 snprintf(old_vfs_data_file, LL_MAX_PATH, "%s%s%s", dir.c_str(), gDirUtilp->getDirDelimiter().c_str(), found_file.c_str());
02699
02700 S32 start_pos;
02701 S32 length = strlen(found_file.c_str());
02702 for (start_pos = length - 1; start_pos >= 0; start_pos--)
02703 {
02704 if (found_file[start_pos] == '.')
02705 {
02706 start_pos++;
02707 break;
02708 }
02709 }
02710 if (start_pos > 0)
02711 {
02712 sscanf(found_file.c_str() + start_pos, "%d", &old_salt);
02713 }
02714 LL_DEBUGS("AppCache") << "Default vfs data file not present, found: " << old_vfs_data_file << " Old salt: " << old_salt << llendl;
02715 }
02716 }
02717
02718 snprintf(old_vfs_index_file, LL_MAX_PATH, "%s%u",
02719 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE).c_str(),
02720 old_salt);
02721
02722 stat_result = LLFile::stat(old_vfs_index_file, &s);
02723 if (stat_result)
02724 {
02725
02726 LL_WARNS("AppCache") << "Bad or missing vfx index file " << old_vfs_index_file << LL_ENDL;
02727 LL_WARNS("AppCache") << "Removing old vfs data file " << old_vfs_data_file << LL_ENDL;
02728 LLFile::remove(old_vfs_data_file);
02729 LLFile::remove(old_vfs_index_file);
02730
02731
02732 std::string dir;
02733 dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
02734
02735 std::string mask;
02736 mask = gDirUtilp->getDirDelimiter();
02737 mask += VFS_DATA_FILE_BASE;
02738 mask += "*";
02739
02740 gDirUtilp->deleteFilesInDir(dir, mask);
02741
02742 mask = gDirUtilp->getDirDelimiter();
02743 mask += VFS_INDEX_FILE_BASE;
02744 mask += "*";
02745
02746 gDirUtilp->deleteFilesInDir(dir, mask);
02747 }
02748
02749 snprintf(new_vfs_data_file, LL_MAX_PATH, "%s%u",
02750 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE).c_str(),
02751 new_salt);
02752
02753 snprintf(new_vfs_index_file, LL_MAX_PATH, "%s%u", gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE).c_str(),
02754 new_salt);
02755
02756
02757 strncpy(static_vfs_data_file, gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2").c_str(), LL_MAX_PATH -1);
02758 static_vfs_data_file[LL_MAX_PATH -1] = '\0';
02759 strncpy(static_vfs_index_file, gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2").c_str(), LL_MAX_PATH -1);
02760 static_vfs_index_file[LL_MAX_PATH -1] = '\0';
02761
02762 if (resize_vfs)
02763 {
02764 LL_DEBUGS("AppCache") << "Removing old vfs and re-sizing" << LL_ENDL;
02765
02766 LLFile::remove(old_vfs_data_file);
02767 LLFile::remove(old_vfs_index_file);
02768 }
02769 else if (old_salt != new_salt)
02770 {
02771
02772 LL_DEBUGS("AppCache") << "Renaming " << old_vfs_data_file << " to " << new_vfs_data_file << LL_ENDL;
02773 LL_DEBUGS("AppCache") << "Renaming " << old_vfs_index_file << " to " << new_vfs_index_file << LL_ENDL;
02774 LLFile::rename(old_vfs_data_file, new_vfs_data_file);
02775 LLFile::rename(old_vfs_index_file, new_vfs_index_file);
02776 }
02777
02778
02779 gSavedSettings.setU32("VFSSalt", new_salt);
02780
02781
02782 gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
02783 if( VFSVALID_BAD_CORRUPT == gVFS->getValidState() )
02784 {
02785
02786
02787 LL_WARNS("AppCache") << "VFS corrupt, deleted. Making new VFS." << LL_ENDL;
02788 delete gVFS;
02789 gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
02790 }
02791
02792 gStaticVFS = new LLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
02793
02794 BOOL success = gVFS->isValid() && gStaticVFS->isValid();
02795 if( !success )
02796 {
02797 return false;
02798 }
02799 else
02800 {
02801 LLVFile::initClass();
02802 return true;
02803 }
02804 }
02805
02806 void LLAppViewer::purgeCache()
02807 {
02808 LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl;
02809 LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
02810 std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
02811 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
02812 }
02813
02814 const LLString& LLAppViewer::getSecondLifeTitle() const
02815 {
02816 return gSecondLife;
02817 }
02818
02819 const LLString& LLAppViewer::getWindowTitle() const
02820 {
02821 return gWindowTitle;
02822 }
02823
02824 void LLAppViewer::resetURIs() const
02825 {
02826
02827 gLoginURIs.clear();
02828 gHelperURI.clear();
02829 }
02830
02831 const std::vector<std::string>& LLAppViewer::getLoginURIs() const
02832 {
02833 if (gLoginURIs.empty())
02834 {
02835
02836 gLoginURIs.push_back(gGridInfo[gGridChoice].mLoginURI);
02837 }
02838 return gLoginURIs;
02839 }
02840
02841 const std::string& LLAppViewer::getHelperURI() const
02842 {
02843 if (gHelperURI.empty())
02844 {
02845
02846 gHelperURI = gGridInfo[gGridChoice].mHelperURI;
02847 }
02848 return gHelperURI;
02849 }
02850
02851 void LLAppViewer::addLoginURI(const std::string& uri)
02852 {
02853
02854
02855 gLoginURIs.push_back(uri);
02856
02857 const std::string& top_uri = getLoginURIs()[0];
02858 int i = 0;
02859 for(; i < GRID_INFO_COUNT; ++i)
02860 {
02861 if(top_uri == gGridInfo[i].mLoginURI)
02862 {
02863 gGridChoice = (EGridInfo)i;
02864 break;
02865 }
02866 }
02867
02868 if(GRID_INFO_COUNT == i)
02869 {
02870 gGridChoice = GRID_INFO_OTHER;
02871 }
02872 }
02873
02874 void LLAppViewer::setHelperURI(const std::string& uri)
02875 {
02876 gHelperURI = uri;
02877 }
02878
02879
02880 void finish_disconnect(S32 option, void* userdata)
02881 {
02882 if (1 == option)
02883 {
02884 LLAppViewer::instance()->forceQuit();
02885 }
02886 }
02887
02888
02889 void finish_forced_disconnect(S32 , void* )
02890 {
02891 LLAppViewer::instance()->forceQuit();
02892 }
02893
02894
02895 void LLAppViewer::forceDisconnect(const LLString& mesg)
02896 {
02897 if (gDoDisconnect)
02898 {
02899
02900
02901 return;
02902 }
02903
02904
02905 LLString big_reason = LLAgent::sTeleportErrorMessages[mesg];
02906 if ( big_reason.size() == 0 )
02907 {
02908 big_reason = mesg;
02909 }
02910
02911 LLStringBase<char>::format_map_t args;
02912 gDoDisconnect = TRUE;
02913
02914 if (LLStartUp::getStartupState() < STATE_STARTED)
02915 {
02916
02917 args["[ERROR_MESSAGE]"] = big_reason;
02918 gViewerWindow->alertXml("ErrorMessage", args, finish_forced_disconnect);
02919 }
02920 else
02921 {
02922 args["[MESSAGE]"] = big_reason;
02923 gViewerWindow->alertXml("YouHaveBeenLoggedOut", args, finish_disconnect );
02924 }
02925 }
02926
02927 void LLAppViewer::badNetworkHandler()
02928 {
02929
02930 gMessageSystem->dumpPacketToLog();
02931
02932
02933
02934
02935 mPurgeOnExit = TRUE;
02936
02937 #if LL_WINDOWS
02938
02939 LLWinDebug::generateCrashStacks(NULL);
02940 #endif
02941 LLAppViewer::handleSyncViewerCrash();
02942 LLAppViewer::handleViewerCrash();
02943
02944 std::ostringstream message;
02945 message <<
02946 "The viewer has detected mangled network data indicative\n"
02947 "of a bad upstream network connection or an incomplete\n"
02948 "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n"
02949 " \n"
02950 "Try uninstalling and reinstalling to see if this resolves \n"
02951 "the issue. \n"
02952 " \n"
02953 "If the problem continues, see the Tech Support FAQ at: \n"
02954 "www.secondlife.com/support";
02955 forceDisconnect(message.str());
02956 }
02957
02958
02959
02960
02961 void LLAppViewer::saveFinalSnapshot()
02962 {
02963 if (!mSavedFinalSnapshot && !gNoRender)
02964 {
02965 gSavedSettings.setVector3d("FocusPosOnLogout", gAgent.calcFocusPositionTargetGlobal());
02966 gSavedSettings.setVector3d("CameraPosOnLogout", gAgent.calcCameraPositionTargetGlobal());
02967 gViewerWindow->setCursor(UI_CURSOR_WAIT);
02968 gAgent.changeCameraToThirdPerson( FALSE );
02969 gSavedSettings.setBOOL("ShowParcelOwners", FALSE);
02970 idle();
02971
02972 LLString snap_filename = gDirUtilp->getLindenUserDir();
02973 snap_filename += gDirUtilp->getDirDelimiter();
02974 snap_filename += SCREEN_LAST_FILENAME;
02975
02976 gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE);
02977 mSavedFinalSnapshot = TRUE;
02978 }
02979 }
02980
02981 void LLAppViewer::loadNameCache()
02982 {
02983 if (!gCacheName) return;
02984
02985 std::string name_cache;
02986 name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
02987 llifstream cache_file(name_cache.c_str());
02988 if(cache_file.is_open())
02989 {
02990 if(gCacheName->importFile(cache_file)) return;
02991 }
02992
02993
02994
02995 LLFILE* name_cache_fp = LLFile::fopen(name_cache.c_str(), "r");
02996 if (name_cache_fp)
02997 {
02998 gCacheName->importFile(name_cache_fp);
02999 fclose(name_cache_fp);
03000 }
03001 }
03002
03003 void LLAppViewer::saveNameCache()
03004 {
03005 if (!gCacheName) return;
03006
03007 std::string name_cache;
03008 name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
03009 llofstream cache_file(name_cache.c_str());
03010 if(cache_file.is_open())
03011 {
03012 gCacheName->exportFile(cache_file);
03013 }
03014 }
03015
03016 bool LLAppViewer::isInProductionGrid()
03017 {
03018
03019
03020 const std::string& loginURI = getLoginURIs()[0];
03021 return (loginURI == gGridInfo[GRID_INFO_AGNI].mLoginURI);
03022 }
03023
03024
03031 class LLFrameStatsTimer : public LLFrameTimer
03032 {
03033 public:
03034 LLFrameStatsTimer(F64 elapsed_already = 0.0)
03035 : LLFrameTimer()
03036 {
03037 mStartTime -= elapsed_already;
03038 }
03039 };
03040
03042
03043
03044
03045
03047 void LLAppViewer::idle()
03048 {
03049
03050 static LLTimer idle_timer;
03051
03052 LLFrameTimer::updateFrameTime();
03053 LLEventTimer::updateClass();
03054 LLCriticalDamp::updateInterpolants();
03055 LLMortician::updateClass();
03056 F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
03057
03058
03059
03060
03061 const F32 MIN_FRAME_RATE = 1.f;
03062 const F32 MAX_FRAME_RATE = 200.f;
03063
03064 F32 frame_rate_clamped = 1.f / dt_raw;
03065 frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE);
03066 gFrameDTClamped = 1.f / frame_rate_clamped;
03067
03068
03069
03070 gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f;
03071
03072 F32 qas = gSavedSettings.getF32("QuitAfterSeconds");
03073 if (qas > 0.f)
03074 {
03075 if (gRenderStartTime.getElapsedTimeF32() > qas)
03076 {
03077 LLAppViewer::instance()->forceQuit();
03078 }
03079 }
03080
03081
03082
03083 request_initial_instant_messages();
03084
03086
03087
03088
03089
03090 if (LLStartUp::getStartupState() < STATE_STARTED)
03091 {
03092
03093 if (!idle_startup())
03094 {
03095 return;
03096 }
03097 }
03098
03099
03100 F32 yaw = 0.f;
03101
03102 if (!gDisconnected)
03103 {
03104 LLFastTimer t(LLFastTimer::FTM_NETWORK);
03105
03106 LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC));
03107
03108
03110
03111
03112
03113
03114 if (gSavedSettings.getBOOL("RotateRight"))
03115 {
03116 gAgent.moveYaw(-1.f);
03117 }
03118
03119
03120 gAgentPilot.updateTarget();
03121 gAgent.autoPilot(&yaw);
03122
03123 static LLFrameTimer agent_update_timer;
03124 static U32 last_control_flags;
03125
03126
03127 F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
03128 BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags());
03129
03130 if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
03131 {
03132
03133 last_control_flags = gAgent.getControlFlags();
03134 send_agent_update(TRUE);
03135 agent_update_timer.reset();
03136 }
03137 }
03138
03140
03141
03142
03143
03144
03145 {
03146
03147
03148
03149 static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD);
03150 reset_statistics();
03151
03152
03153
03154 if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected)
03155 {
03156 llinfos << "Transmitting sessions stats" << llendl;
03157 send_stats();
03158 viewer_stats_timer.reset();
03159 }
03160
03161
03162 static LLFrameTimer object_debug_timer;
03163 if (object_debug_timer.getElapsedTimeF32() > 5.f)
03164 {
03165 object_debug_timer.reset();
03166 if (gObjectList.mNumDeadObjectUpdates)
03167 {
03168 llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
03169 gObjectList.mNumDeadObjectUpdates = 0;
03170 }
03171 if (gObjectList.mNumUnknownKills)
03172 {
03173 llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
03174 gObjectList.mNumUnknownKills = 0;
03175 }
03176 if (gObjectList.mNumUnknownUpdates)
03177 {
03178 llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
03179 gObjectList.mNumUnknownUpdates = 0;
03180 }
03181 }
03182 gFrameStats.addFrameData();
03183 }
03184
03185 if (!gDisconnected)
03186 {
03187 LLFastTimer t(LLFastTimer::FTM_NETWORK);
03188
03190
03191
03192
03193
03194
03195
03196
03197 gFrameStats.start(LLFrameStats::IDLE_NETWORK);
03198 idleNetwork();
03199 stop_glerror();
03200
03201 gFrameStats.start(LLFrameStats::AGENT_MISC);
03202
03203
03204 idle_afk_check();
03205
03206
03207 update_statistics(gFrameCount);
03208 }
03209
03211
03212
03213
03214
03215
03216 {
03217
03218
03219
03220 gEventNotifier.update();
03221
03222 gIdleCallbacks.callFunctions();
03223 }
03224
03225 if (gDisconnected)
03226 {
03227 return;
03228 }
03229
03230 gViewerWindow->handlePerFrameHover();
03231
03233
03234
03235 LLCoordGL current_mouse = gViewerWindow->getCurrentMouse();
03236
03237 {
03238
03239
03240 LLSelectMgr::getInstance()->deselectAllIfTooFar();
03241
03242 }
03243
03244 {
03245
03246 gGestureManager.update();
03247
03248 gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
03249 }
03250
03251 {
03252 LLFastTimer t(LLFastTimer::FTM_OBJECTLIST_UPDATE);
03253 gFrameStats.start(LLFrameStats::OBJECT_UPDATE);
03254
03255 if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
03256 {
03257 gObjectList.update(gAgent, *LLWorld::getInstance());
03258 }
03259 }
03260
03262
03263
03264
03265
03266
03267 {
03268 LLFastTimer t(LLFastTimer::FTM_CLEANUP);
03269 gFrameStats.start(LLFrameStats::CLEAN_DEAD);
03270 gObjectList.cleanDeadObjects();
03271 LLDrawable::cleanupDeadDrawables();
03272 }
03273
03274
03275
03276
03277
03278
03280
03281
03282
03283
03284
03285
03286
03287 {
03288 gFrameStats.start(LLFrameStats::UPDATE_EFFECTS);
03289 LLSelectMgr::getInstance()->updateEffects();
03290 LLHUDManager::getInstance()->cleanupEffects();
03291 LLHUDManager::getInstance()->sendEffects();
03292 }
03293
03294 stop_glerror();
03295
03297
03298
03299
03300
03301 {
03302 LLFastTimer t(LLFastTimer::FTM_NETWORK);
03303 gVLManager.unpackData();
03304 }
03305
03307
03308
03309
03310
03311 LLWorld::getInstance()->updateVisibilities();
03312 {
03313 const F32 max_region_update_time = .001f;
03314 LLFastTimer t(LLFastTimer::FTM_REGION_UPDATE);
03315 LLWorld::getInstance()->updateRegions(max_region_update_time);
03316 }
03317
03319
03320
03321
03322 if (!gNoRender)
03323 {
03324 LLWorld::getInstance()->updateClouds(gFrameDTClamped);
03325 gSky.propagateHeavenlyBodies(gFrameDTClamped);
03326
03327
03328 LLVector3 wind_position_region;
03329 static LLVector3 average_wind;
03330
03331 LLViewerRegion *regionp;
03332 regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal());
03333 if (regionp)
03334 {
03335 gWindVec = regionp->mWind.getVelocity(wind_position_region);
03336
03337
03338
03339 average_wind = regionp->mWind.getAverage();
03340 F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
03341
03342 gSky.setCloudDensityAtAgent(cloud_density);
03343 gSky.setWind(average_wind);
03344
03345 }
03346 else
03347 {
03348 gWindVec.setVec(0.0f, 0.0f, 0.0f);
03349 }
03350 }
03351 stop_glerror();
03352
03354
03355
03356
03357
03358
03359 if (!gNoRender)
03360 {
03361 LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE);
03362 gFrameStats.start(LLFrameStats::UPDATE_MOVE);
03363 gPipeline.updateMove();
03364
03365 gFrameStats.start(LLFrameStats::UPDATE_PARTICLES);
03366 LLWorld::getInstance()->updateParticles();
03367 }
03368 stop_glerror();
03369
03370 if (LLViewerJoystick::getInstance()->getOverrideCamera())
03371 {
03372 LLViewerJoystick::getInstance()->moveFlycam();
03373 }
03374 else
03375 {
03376 if (LLToolMgr::getInstance()->inBuildMode())
03377 {
03378 LLViewerJoystick::getInstance()->moveObjects();
03379 }
03380
03381 gAgent.updateCamera();
03382 }
03383
03384
03385 {
03386 LLFastTimer t(LLFastTimer::FTM_LOD_UPDATE);
03387 gObjectList.updateApparentAngles(gAgent);
03388 }
03389
03390 {
03391 gFrameStats.start(LLFrameStats::AUDIO);
03392 LLFastTimer t(LLFastTimer::FTM_AUDIO_UPDATE);
03393
03394 if (gAudiop)
03395 {
03396 audio_update_volume(false);
03397 audio_update_listener();
03398 audio_update_wind(false);
03399
03400
03401 const F32 max_audio_decode_time = 0.002f;
03402 gAudiop->idle(max_audio_decode_time);
03403 }
03404 }
03405
03406
03407
03408
03409 if (mQuitRequested)
03410 {
03411 idleShutdown();
03412 }
03413
03414 stop_glerror();
03415 }
03416
03417 void LLAppViewer::idleShutdown()
03418 {
03419
03420 if (LLModalDialog::activeCount() > 0)
03421 {
03422 return;
03423 }
03424
03425
03426 if(gIMMgr)
03427 {
03428 gIMMgr->disconnectAllSessions();
03429 }
03430
03431
03432 if (gFloaterView
03433 && !gFloaterView->allChildrenClosed())
03434 {
03435 return;
03436 }
03437
03438 static bool saved_snapshot = false;
03439 if (!saved_snapshot)
03440 {
03441 saved_snapshot = true;
03442 saveFinalSnapshot();
03443 return;
03444 }
03445
03446 const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
03447
03448 S32 pending_uploads = gAssetStorage->getNumPendingUploads();
03449 if (pending_uploads > 0
03450 && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
03451 && !logoutRequestSent())
03452 {
03453 static S32 total_uploads = 0;
03454
03455 total_uploads = llmax(total_uploads, pending_uploads);
03456 gViewerWindow->setShowProgress(TRUE);
03457 S32 finished_uploads = total_uploads - pending_uploads;
03458 F32 percent = 100.f * finished_uploads / total_uploads;
03459 gViewerWindow->setProgressPercent(percent);
03460 char buffer[MAX_STRING];
03461 snprintf(buffer, MAX_STRING, "Saving final data...");
03462 gViewerWindow->setProgressString(buffer);
03463 return;
03464 }
03465
03466
03467 if( !logoutRequestSent() )
03468 {
03469 sendLogoutRequest();
03470
03471
03472 gViewerWindow->setShowProgress(TRUE);
03473 gViewerWindow->setProgressPercent(100.f);
03474 gViewerWindow->setProgressString("Logging out...");
03475 return;
03476 }
03477
03478
03479 if( logoutRequestSent()
03480 && gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime )
03481 {
03482 forceQuit();
03483 return;
03484 }
03485 }
03486
03487 void LLAppViewer::sendLogoutRequest()
03488 {
03489 if(!mLogoutRequestSent)
03490 {
03491 LLMessageSystem* msg = gMessageSystem;
03492 msg->newMessageFast(_PREHASH_LogoutRequest);
03493 msg->nextBlockFast(_PREHASH_AgentData);
03494 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03495 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03496 gAgent.sendReliableMessage();
03497
03498 gLogoutTimer.reset();
03499 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
03500 mLogoutRequestSent = TRUE;
03501
03502 gVoiceClient->leaveChannel();
03503
03504
03505 gLogoutInProgress = TRUE;
03506 mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
03507 mLogoutMarkerFile = ll_apr_file_open(mLogoutMarkerFileName, LL_APR_W);
03508 if (mLogoutMarkerFile)
03509 {
03510 llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl;
03511 }
03512 else
03513 {
03514 llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl;
03515 }
03516 apr_file_close(mLogoutMarkerFile);
03517 }
03518 }
03519
03520
03521
03522
03523
03524 #define TIME_THROTTLE_MESSAGES
03525
03526 #ifdef TIME_THROTTLE_MESSAGES
03527 #define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
03528 static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
03529 #endif
03530
03531 void LLAppViewer::idleNetwork()
03532 {
03533 gObjectList.mNumNewObjects = 0;
03534 S32 total_decoded = 0;
03535
03536 if (!gSavedSettings.getBOOL("SpeedTest"))
03537 {
03538 LLFastTimer t(LLFastTimer::FTM_IDLE_NETWORK);
03539
03540
03541 gCacheName->processPending();
03542
03543 LLTimer check_message_timer;
03544
03545 stop_glerror();
03546 const S64 frame_count = gFrameCount;
03547 F32 total_time = 0.0f;
03548 while (gMessageSystem->checkAllMessages(frame_count, gServicePump))
03549 {
03550 if (gDoDisconnect)
03551 {
03552
03553
03554
03555 break;
03556 }
03557 stop_glerror();
03558
03559 total_decoded++;
03560 gPacketsIn++;
03561
03562 if (total_decoded > MESSAGE_MAX_PER_FRAME)
03563 {
03564 break;
03565 }
03566
03567 #ifdef TIME_THROTTLE_MESSAGES
03568
03569
03570
03571
03572 total_time = check_message_timer.getElapsedTimeF32();
03573 if (total_time >= CheckMessagesMaxTime)
03574 break;
03575 #endif
03576 }
03577
03578 gMessageSystem->processAcks();
03579
03580 #ifdef TIME_THROTTLE_MESSAGES
03581 if (total_time >= CheckMessagesMaxTime)
03582 {
03583
03584 CheckMessagesMaxTime *= 1.035f;
03585 }
03586 else
03587 {
03588
03589 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
03590 }
03591 #endif
03592
03593
03594
03595
03596 gAgent.resetControlFlags();
03597 stop_glerror();
03598
03599
03600
03601 S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
03602
03603 if( remaining_possible_decodes <= 0 )
03604 {
03605 llinfos << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << llendl;
03606 }
03607
03608 if (gPrintMessagesThisFrame)
03609 {
03610 llinfos << "Decoded " << total_decoded << " msgs this frame!" << llendl;
03611 gPrintMessagesThisFrame = FALSE;
03612 }
03613 }
03614
03615 gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
03616
03617
03618 gXferManager->retransmitUnackedPackets();
03619 gAssetStorage->checkForTimeouts();
03620
03621 gViewerThrottle.updateDynamicThrottle();
03622 }
03623
03624 void LLAppViewer::disconnectViewer()
03625 {
03626 if (gDisconnected)
03627 {
03628 return;
03629 }
03630
03631
03632
03633
03634
03635 llinfos << "Disconnecting viewer!" << llendl;
03636
03637
03638 gFrameStats.dump();
03639
03640
03641 gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
03642
03643
03644 if (!gNoRender)
03645 {
03646 if (gFloaterView)
03647 {
03648 gFloaterView->restoreAll();
03649 }
03650 }
03651
03652 if (LLSelectMgr::getInstance())
03653 {
03654 LLSelectMgr::getInstance()->deselectAll();
03655 }
03656
03657 if (!gNoRender)
03658 {
03659
03660 gInventory.cache(gAgent.getInventoryRootID(), gAgent.getID());
03661 if(gInventoryLibraryRoot.notNull() && gInventoryLibraryOwner.notNull())
03662 {
03663 gInventory.cache(gInventoryLibraryRoot, gInventoryLibraryOwner);
03664 }
03665 }
03666
03667 saveNameCache();
03668
03669
03670 LLInventoryView::cleanup();
03671
03672
03673 gAgent.cleanup();
03674
03675
03676
03677 LLWorld::getInstance()->destroyClass();
03678
03679 cleanup_xfer_manager();
03680 gDisconnected = TRUE;
03681 }
03682
03683 void LLAppViewer::forceErrorLLError()
03684 {
03685 llerrs << "This is an llerror" << llendl;
03686 }
03687
03688 void LLAppViewer::forceErrorBreakpoint()
03689 {
03690 #ifdef LL_WINDOWS
03691 DebugBreak();
03692 #endif
03693 return;
03694 }
03695
03696 void LLAppViewer::forceErrorBadMemoryAccess()
03697 {
03698 S32* crash = NULL;
03699 *crash = 0xDEADBEEF;
03700 return;
03701 }
03702
03703 void LLAppViewer::forceErrorInifiniteLoop()
03704 {
03705 while(true)
03706 {
03707 ;
03708 }
03709 return;
03710 }
03711
03712 void LLAppViewer::forceErrorSoftwareException()
03713 {
03714
03715 throw;
03716 }
03717
03718 void LLAppViewer::startMainloopTimeout(F32 secs)
03719 {
03720 if(secs < 0.0f)
03721 {
03722 secs = gSavedSettings.getF32("MainloopTimeoutDefault");
03723 }
03724
03725 mMainloopTimeout->setTimeout(secs);
03726 mMainloopTimeout->start();
03727 }
03728
03729 void LLAppViewer::stopMainloopTimeout()
03730 {
03731 mMainloopTimeout->stop();
03732 }