00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "viewer.h"
00035 
00036 #include "llparcel.h"
00037 #include "llviewerparcelmgr.h"
00038 #include "llviewerjoystick.h"
00039 
00040 
00041 #include <errno.h>
00042 #include <stdexcept>
00043 #if LL_WINDOWS
00044 #       include <share.h>
00045 #else
00046 #       include <sys/file.h>
00047 #       include <signal.h>
00048 #endif
00049 #include <sys/stat.h>
00050 #include <memory>
00051 #include <boost/tokenizer.hpp>
00052 
00053 #if LL_WINDOWS
00054 #include <fcntl.h>              
00055 #include <io.h>                 
00056 #include <errorrep.h>   
00057 #include <process.h>    
00058 #include <tchar.h>              
00059 
00060 #if LL_WINDOWS && _MSC_VER < 1400
00061 
00062 #else
00063 #define LL_USE_SMARTHEAP 0
00064 #endif
00065 
00066 #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
00067 #include "smrtheap/smrtheap.h"
00068 #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
00069 
00070 #elif LL_DARWIN || LL_LINUX || LL_SOLARIS
00071 
00072   #     include <sys/socket.h>
00073 
00074   #     include <netinet/in.h>
00075   #     include <arpa/inet.h>   
00076 
00077   #if LL_LINUX
00078   #     include <dlfcn.h>               
00079   #     include <execinfo.h>            
00080   #     ifndef LL_ELFBIN
00081   #define LL_ELFBIN 1
00082   #     endif // LL_ELFBIN
00083   #     if LL_ELFBIN
00084   #          include <cxxabi.h>         
00085   #          include "ELFIO.h"          
00086   #     endif // LL_ELFBIN
00087   #elif LL_SOLARIS
00088   #     include <sys/types.h>
00089   #     include <unistd.h>
00090   #     include <fcntl.h>
00091   #     include <ucontext.h>
00092   #endif
00093 
00094   #if LL_DARWIN
00095     #include <Carbon/Carbon.h>
00096     
00097     #ifdef check
00098             #undef check
00099     #endif
00100     #ifdef verify
00101             #undef verify
00102     #endif // verify
00103     #ifdef require
00104             #undef require
00105     #endif
00106   #endif
00107 #endif // !LL_WINDOWS
00108 
00109 
00110 #define LL_SEND_CRASH_REPORTS 1
00111 
00112 
00113 
00114 
00115 
00116 
00117 #include "audioengine.h" 
00118 #include "llcommon.h" 
00119 #include "llapr.h" 
00120 #include "llcachename.h"
00121 #include "llcurl.h"
00122 #include "llcriticaldamp.h"
00123 #include "lldir.h"
00124 #include "lleconomy.h"
00125 #include "llerrorcontrol.h"
00126 #include "llhttpnode.h"
00127 #include "llflexibleobject.h"
00128 #include "llfasttimer.h"
00129 #include "llfocusmgr.h"
00130 #include "llgroupmgr.h"
00131 #include "llimage.h"
00132 #include "llimageworker.h"
00133 #include "lllfsthread.h"
00134 #include "llmemtype.h"
00135 #include "llmd5.h"
00136 #include "llsecondlifeurls.h"
00137 #include "llversionviewer.h"
00138 #include "llvfile.h"
00139 #include "llvfs.h"
00140 #include "llwindow.h"           
00141 #include "llworkerthread.h"
00142 #include "llvfsthread.h"
00143 #include "llxfermanager.h"
00144 #include "message.h"
00145 #include "llvoavatar.h"
00146 #include "llglslshader.h"
00147 
00148 
00149 
00150 
00151 
00152 #include "llagent.h"
00153 #include "llagentpilot.h"
00154 #include "llbutton.h" 
00155 #include "llcallbacklist.h"
00156 #include "llchatbar.h"
00157 
00158 #include "llconsole.h"
00159 #include "llcontainerview.h"
00160 #include "lldebugview.h"
00161 #include "lldrawpoolbump.h"
00162 #include "lldrawpoolterrain.h"
00163 #include "lleventnotifier.h"
00164 #include "llfasttimerview.h"
00165 #include "llfeaturemanager.h"
00166 #include "llfirstuse.h"
00167 #include "llfloateravatarlist.h"
00168 #include "llfloateractivespeakers.h"
00169 #include "llfloatertools.h"
00170 #include "llfloaterworldmap.h"
00171 #include "llfloaterhtmlhelp.h"
00172 #include "llfloatersaveavatar.h"
00173 #include "llfloatersnapshot.h"
00174 #include "llfloatereventlog.h"
00175 #include "llfolderview.h"
00176 #include "llframestats.h"
00177 #include "llgesturemgr.h"
00178 #include "llhoverview.h"
00179 #include "llhudeffecttrail.h"
00180 #include "llhudmanager.h"
00181 #include "llhttpclient.h"
00182 #include "llimview.h"
00183 #include "llimpanel.h"
00184 #include "llinventorymodel.h"
00185 #include "llinventoryview.h"
00186 #include "llkeyboard.h"
00187 #include "llkeyframemotion.h"
00188 #include "llpanellogin.h"
00189 #include "llmutelist.h"
00190 #include "llmenugl.h"
00191 #include "llnamelistctrl.h"
00192 #include "llnamebox.h"
00193 #include "llnameeditor.h"
00194 #include "llpumpio.h"
00195 #include "llnotify.h"
00196 #include "llregionnamecache.h"
00197 #include "llselectmgr.h"
00198 #include "llsky.h"
00199 #include "llsrv.h"
00200 #include "llstartup.h"
00201 #include "llstatusbar.h"
00202 #include "llsurface.h"
00203 #include "lltexlayer.h"
00204 #include "lltexturecache.h"
00205 #include "lltexturefetch.h"
00206 #include "lltoolbar.h"
00207 #include "lltoolmgr.h"
00208 #include "lltracker.h"
00209 #include "lltrustnet.h"
00210 #include "llurldispatcher.h"
00211 #include "llurlsimstring.h"
00212 #include "llurlwhitelist.h"
00213 #include "llv4math.h"           
00214 #include "llviewerbuild.h"
00215 #include "llviewercamera.h"
00216 #include "llviewercontrol.h"
00217 #include "llviewerjointmesh.h"
00218 #include "llviewerimagelist.h"
00219 #include "llviewerkeyboard.h"
00220 #include "llviewermenu.h"
00221 #include "llviewermessage.h"
00222 #include "llviewernetwork.h"
00223 #include "llviewerobjectlist.h"
00224 #include "llviewerparcelmgr.h"
00225 #include "llviewerregion.h"
00226 #include "llviewerstats.h"
00227 #include "llviewerthrottle.h"
00228 #include "llvieweruictrlfactory.h"
00229 #include "llviewerwindow.h"
00230 #include "llvlmanager.h"
00231 #include "llvoavatar.h"
00232 #include "llvograss.h"
00233 #include "llvotree.h"
00234 #include "llvovolume.h"         
00235 #include "llvowater.h"
00236 #include "llvolume.h"
00237 #include "llvolumemgr.h"
00238 #include "llvolumemessage.h"
00239 #include "llweb.h"
00240 #include "llworld.h"
00241 #include "llworldmap.h"
00242 #include "llworldmapview.h"
00243 #include "pipeline.h"
00244 #include "llface.h"
00245 #include "audiosettings.h"
00246 #include "res/resource.h"
00247 #include "llvoiceclient.h"
00248 
00249 #if LL_WINDOWS
00250 #include "llwindebug.h"
00251 #include "lldxhardware.h"
00252 #include "llwindowwin32.h"
00253 
00254 
00255 #ifndef LL_LOGITECH_LCD_H
00256 #include "lllogitechlcd.h"
00257 #endif
00258 extern void CreateLCDDebugWindows();
00259 
00260 #endif // LL_WINDOWS
00261 
00262 #if LL_QUICKTIME_ENABLED
00263 #if LL_DARWIN
00264 #include <QuickTime/QuickTime.h>
00265 #else
00266 
00267 #include "MacTypes.h"
00268 #include "QTML.h"
00269 #include "Movies.h"
00270 #include "FixMath.h"
00271 #endif
00272 #endif
00273 
00274 #if LL_GSTREAMER_ENABLED
00275 
00276 
00277 void UnloadGStreamer();
00278 #endif // LL_GSTREAMER_ENABLED
00279 
00280 #include "llmediaengine.h"
00281 
00282 #if LL_LIBXUL_ENABLED
00283 #include "llmozlib.h"
00284 #endif // LL_LIBXUL_ENABLED
00285 
00287 
00289 
00290 void errorCallback(const std::string &error_string);
00291 S32 gCrashBehavior = CRASH_BEHAVIOR_ASK;
00292 void (*gCrashCallback)(void) = NULL;
00293 BOOL gReportedCrash = FALSE;
00294 
00295 bool gVerifySSLCert = true;
00296 
00297 BOOL gHandleKeysAsync = FALSE;
00298 
00299 
00300 BOOL gProbeHardware = TRUE;
00301 std::string gSerialNumber;
00302 
00304 
00306 
00307 BOOL gAgentMovementCompleted = FALSE;
00308 BOOL gHaveSavedSnapshot = FALSE;
00309 
00310 S32 gYieldMS = 0;
00311 BOOL gYieldTime = FALSE;
00312 
00313 const U32 COLLISION_LIST_DEPTH = 300;   
00314 const S32 MAX_CONSOLE_LINES = 500;
00315 const S32 NUM_SESSIONS_BEFORE_SHOW_PROFILE = 5;
00316 const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; 
00317 
00318 const char *VFS_DATA_FILE_BASE                  = "data.db2.x.";
00319 const char *VFS_INDEX_FILE_BASE                 = "index.db2.x.";
00320 
00321 F32 gSimLastTime;
00322 F32 gSimFrames;
00323 
00324 
00325 
00327 
00329 
00330 
00331 
00332 
00333 #if LL_WINDOWS
00334 llLCD   *gLcdScreen = NULL; 
00335 #endif
00336 
00337 LLString gSecondLife;
00338 LLString gWindowTitle;
00339 static char sWindowClass[] = "Dale's Unofficial Viewer";
00340 LLString gDisabledMessage;
00341 BOOL gHideLinks = FALSE;
00342 
00343 
00344 BOOL gInProductionGrid  = FALSE;
00345 
00346 
00347 #if LL_RELEASE_FOR_DOWNLOAD
00348 
00349 #ifndef APPLE_PREVIEW
00350 static EUserServerDomain UserServerDefaultChoice = USERSERVER_AGNI;
00351 #else
00352 static EUserServerDomain UserServerDefaultChoice = USERSERVER_ADITI;
00353 #endif
00354 #else
00355 
00356 static EUserServerDomain UserServerDefaultChoice = USERSERVER_DMZ;
00357 #endif
00358 
00359 #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
00360 BOOL                            gHackGodmode = FALSE;
00361 #endif
00362 
00363 std::vector<std::string>        gLoginURIs;
00364 static std::string      gHelperURI;
00365 
00366 LLAgent                         gAgent;
00367 LLPipeline                      gPipeline;
00368 
00369 
00370 
00371 BOOL                            gDoDisconnect = FALSE;
00372 BOOL                            gDisconnected = FALSE;
00373 
00374 
00375 BOOL                            gPurgeOnExit = FALSE;
00376 BOOL                            gPurgeCache = FALSE;
00377 
00378 
00379 #if LL_RELEASE_FOR_DOWNLOAD
00380 BOOL                            gMultipleViewersOK = FALSE;
00381 #else
00382 BOOL                            gMultipleViewersOK = TRUE;
00383 #endif
00384 BOOL                            gSecondInstance = FALSE;
00385 BOOL                            gDisableVoice = FALSE;
00386 
00387 LLString                        gArgs;
00388 
00389 
00390 BOOL                            gQuit = FALSE;
00391 
00392 BOOL                            gQuitRequested = FALSE;
00393 LLString                        gLaunchFileOnQuit;
00394 BOOL                            gDoneLogout = FALSE;
00395 
00396 BOOL                            gInitializationComplete = FALSE;        
00397 BOOL                            gAutoLogin = FALSE;
00398 LLString                        gOldSettingsFileName;
00399 BOOL                            gPrintMessagesThisFrame = FALSE;
00400 const char*                     DEFAULT_SETTINGS_FILE = "settings_dale.xml";
00401 const char*                     LEGACY_DEFAULT_SETTINGS_FILE = "settings_dale.ini";
00402 BOOL                            gUseWireframe = FALSE;
00403 LLUUID                          gViewerDigest;  
00404 LLPumpIO*                       gServicePump = NULL;
00405 S32                                     gNumSessions = 0;
00406 
00407 BOOL                            gAllowIdleAFK = TRUE;
00408 F32                                     gAFKTimeout = DEFAULT_AFK_TIMEOUT;
00409 F32                                     gMouseSensitivity = 3.f;
00410 BOOL                            gInvertMouse = FALSE;
00411 BOOL                            gLogoutRequestSent = FALSE;
00412 LLTimer                         gLogoutTimer;
00413 BOOL                            gShowObjectUpdates = FALSE;
00414 
00415 const F32                       LOGOUT_REQUEST_TIME = 6.f;  
00416 F32                                     gLogoutMaxTime = LOGOUT_REQUEST_TIME;
00417 
00418 
00419 F32                             gMapScale = 128.f;
00420 F32                             gMiniMapScale = 128.f;
00421 
00422 
00423 LLSky                           gSky;
00424 
00425 
00426 BOOL                            gDisplayWindInfo = FALSE;
00427 BOOL                            gDisplayCameraPos = FALSE;
00428 BOOL                            gDisplayNearestWater = FALSE;
00429 BOOL                            gDoNearestWaterSearch = FALSE;
00430 BOOL                            gDisplayFOV = FALSE;
00431 
00432 
00433 LLFrameTimer    gRestoreGLTimer;
00434 BOOL                    gRestoreGL = FALSE;
00435 
00436 
00437 
00438 LLVFS* gStaticVFS = NULL;
00439 
00440 
00441 LLTextureCache* gTextureCache = NULL;
00442 LLWorkerThread* gImageDecodeThread = NULL;
00443 LLTextureFetch* gTextureFetch = NULL;
00444 
00445 
00446 FILE *gDebugFile = NULL;        
00447 BOOL gRandomizeFramerate = FALSE;
00448 BOOL gPeriodicSlowFrame = FALSE;
00449 std::map<S32,LLFrameTimer> gDebugTimers;
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 U64 gFrameTime = 0;
00458 F32 gFrameTimeSeconds = 0.f;
00459 F32 gFrameIntervalSeconds = 0.f;
00460 U32     gFrameCount = 0;
00461 U32 gForegroundFrameCount = 0; 
00462 U64     gStartTime = 0; 
00463 U64     gSpaceTime = 0; 
00464 
00465 
00466 LLTimer gRenderStartTime;
00467 LLFrameTimer gForegroundTime;
00468 F32 gQuitAfterSeconds = 0.f;
00469 BOOL gRotateRight = FALSE;
00470 
00471 
00472 
00473 BOOL gPacificDaylightTime = FALSE;
00474 
00475 
00476 
00477 
00478 U32     gSecondsPerDay = 0;
00479 U32     gSecondsPerYear = 0;
00480 
00481 LLString gLastVersionChannel;
00482 
00483 
00484 
00485 
00486 
00487 
00488 LLVector3                       gWindVec(3.0, 3.0, 0.0);
00489 LLVector3                       gRelativeWindVec(0.0, 0.0, 0.0);
00490 
00491 
00492 
00493 
00494 
00495 BOOL gVelocityInterpolate = TRUE; 
00496 BOOL gPingInterpolate = TRUE; 
00497 
00498 
00499 
00500 
00501 
00502 LLMemoryInfo gSysMemory;
00503 LLOSInfo gSysOS;
00504 
00505 
00506 static const char USAGE[] = "\n"
00507 "usage:\tviewer [options]\n"
00508 "options:\n"
00509 " -login <first> <last> <password>     log in as a user\n"
00510 " -autologin                           log in as last saved user\n"
00511 " -loginuri <URI>                      login server and CGI script to use\n"
00512 " -helperuri <URI>                     helper web CGI prefix to use\n"
00513 " -settings <filename>                 specify the filename of a\n"
00514 "                                        configuration file\n"
00515 "                                        default is settings.xml\n"
00516 " -setdefault <variable> <value>       specify the value of a particular\n"
00517 "                                        configuration variable which can be\n"
00518 "                                        overridden by settings.xml\n"
00519 " -set <variable> <value>              specify the value of a particular\n"
00520 "                                        configuration variable that\n"
00521 "                                        overrides all other settings\n"
00522 " -user <user_server_ip>               specify userserver in dotted quad\n"
00523 #if !LL_RELEASE_FOR_DOWNLOAD
00524 " -sim <simulator_ip>                  specify the simulator ip address\n"
00525 #endif
00526 " -god                                     log in as god if you have god access\n"
00527 " -purge                               delete files in cache\n"
00528 " -safe                                reset preferences, run in safe mode\n"
00529 " -noutc                               logs in local time, not UTC\n"
00530 " -nothread                            run vfs in single thread\n"
00531 " -noinvlib                            Do not request inventory library\n"
00532 " -multiple                            allow multiple viewers\n"
00533 " -nomultiple                          block multiple viewers\n"
00534 " -novoice                             disable voice\n"
00535 " -ignorepixeldepth                    ignore pixel depth settings\n"
00536 " -cooperative [ms]                    yield some idle time to local host\n"
00537 " -skin                                ui/branding skin folder to use\n"
00538 #if LL_WINDOWS
00539 " -noprobe                             disable hardware probe\n"
00540 #endif
00541 " -noquicktime                         disable QuickTime movies, speeds startup\n"
00542 " -nopreload                           don't preload UI images or sounds, speeds startup\n"
00543 
00544 
00545 
00546 "\n";
00547 
00548 
00549 
00550 BOOL gGodConnect = FALSE;
00551 BOOL gUseConsole = TRUE;
00552 BOOL gUseAudio = TRUE;
00553 BOOL gUseFMOD = TRUE;
00554 BOOL gLogMessages = FALSE;
00555 BOOL gRequestInventoryLibrary = TRUE;
00556 BOOL gAcceptTOS = FALSE;
00557 BOOL gAcceptCriticalMessage = FALSE;
00558 
00559 std::string gChannelName = LL_CHANNEL;
00560 
00561 LLUUID gInventoryLibraryOwner;
00562 LLUUID gInventoryLibraryRoot;
00563 bool gPreloadImages = true;
00564 bool gPreloadSounds = true;
00565 
00566 LLString gCmdLineFirstName;
00567 LLString gCmdLineLastName;
00568 LLString gCmdLinePassword;
00569 std::map<std::string, std::string> gCommandLineSettings;
00570 std::map<std::string, std::string> gCommandLineForcedSettings;
00571 BOOL gLastExecFroze = FALSE;
00572 BOOL gIgnorePixelDepth = FALSE;
00573 
00574 
00575 LLPointer<LLImageGL> gDisconnectedImagep = NULL;
00576 
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 void init_marker_file();
00601 void init_crash_handler();
00602 void init_logging();
00603 void create_console();
00604 void write_system_info();
00605 int parse_args(int argc, char **argv);
00606 void saved_settings_to_globals();
00607 BOOL init_cache();
00608 void purge_cache();
00609 void cleanup_app();
00610 void disconnect_viewer(void *); 
00611 
00612 
00613 
00614 
00615 void write_debug(const char *str);      
00616 void write_debug(const std::string& str);
00617 void close_debug();                                     
00618 void catch_signals();
00619 void viewer_crash_callback();
00620 void remove_marker_file();
00621 #if !LL_WINDOWS
00622 void release_signals();
00623 #endif
00624 
00625 void bad_network_handler();
00626 
00627 #if LL_WINDOWS
00628 void disable_win_error_reporting();
00629 #endif
00630 std::string get_serial_number();
00631 bool send_url_to_other_instance(const std::string& url);
00632 BOOL another_instance_running();
00633 void main_loop();
00634 
00635 
00636 
00637 
00638 
00639 
00640 void uuid_table_request_file_callback(void **user_data, S32 result, LLExtStat ext_status);
00641 void send_stats();
00642 
00643 
00644 
00645 
00646 #if LL_DARWIN
00647 void init_apple_menu(const char* product);
00648 OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
00649 OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn);
00650 OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata);
00651 OSStatus DisplayReleaseNotes(void);
00652 #endif // LL_DARWIN
00653 
00654 void ui_audio_callback(const LLUUID& uuid)
00655 {
00656         if (gAudiop)
00657         {
00658                 F32 volume = gSavedSettings.getF32("AudioLevelUI");
00659                 gAudiop->triggerSound(uuid, gAgent.getID(), volume);
00660         }
00661 }
00662 
00663 #if LL_WINDOWS
00664 BOOL CALLBACK login_dialog_func(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lparam)
00665 {
00666         char buffer[MAX_STRING];                
00667         switch(msg)
00668         {
00669     case WM_INITDIALOG:
00670                 {
00671                         LLString first_name = gCmdLineFirstName;
00672                         LLString last_name = gCmdLineLastName;
00673                         LLString password = gCmdLinePassword;
00674 
00675                         if (!first_name.empty())
00676                         {
00677                                 SetDlgItemTextA( hwnd, IDC_EDIT_FIRSTNAME, first_name.c_str());
00678                         }
00679                         if (!last_name.empty())
00680                         {
00681                                 SetDlgItemTextA( hwnd, IDC_EDIT_LASTNAME, last_name.c_str());
00682                         }
00683                         if (!password.empty())
00684                         {
00685                                 SetDlgItemTextA( hwnd, IDC_EDIT_PASSWORD, password.c_str());
00686                         }
00687 
00688                         first_name = gSavedSettings.getString("FirstName");
00689                         last_name = gSavedSettings.getString("LastName");
00690                         password = load_password_from_disk();
00691 
00692                         if (!first_name.empty())
00693                         {
00694                                 SetDlgItemTextA( hwnd, IDC_EDIT_FIRSTNAME, first_name.c_str());
00695                         }
00696                         if (!last_name.empty())
00697                         {
00698                                 SetDlgItemTextA( hwnd, IDC_EDIT_LASTNAME, last_name.c_str());
00699                         }
00700                         if (!password.empty())
00701                         {
00702                                 SetDlgItemTextA( hwnd, IDC_EDIT_PASSWORD, password.c_str());
00703                         }
00704 
00705                         
00706                         if (first_name.empty())
00707                         {
00708                                 SetFocus(GetDlgItem(hwnd, IDC_EDIT_FIRSTNAME)); 
00709                         }
00710                         else if (last_name.empty())
00711                         {
00712                                 SetFocus(GetDlgItem(hwnd, IDC_EDIT_LASTNAME)); 
00713                         }
00714                         else if (password.empty())
00715                         {
00716                                 SetFocus(GetDlgItem(hwnd, IDC_EDIT_PASSWORD)); 
00717                         }
00718                         else
00719                         {
00720                                 SetFocus(GetDlgItem(hwnd, IDC_EDIT_FIRSTNAME)); 
00721                         }
00722 
00723                         BOOL remember_password = gSavedSettings.getBOOL("RememberPassword");
00724                         if (remember_password)
00725                         {
00726                                 CheckDlgButton(hwnd, IDC_REMEMBER_PASSWORD, BST_CHECKED);
00727                         }
00728                         else
00729                         {
00730                                 CheckDlgButton(hwnd, IDC_REMEMBER_PASSWORD, BST_UNCHECKED);
00731                         }
00732                         return TRUE;
00733                 }
00734 
00735         case WM_COMMAND:
00736                 switch(LOWORD(wParam))
00737                 {
00738                 case IDOK:
00739                         {
00740                                 
00741                                 if (GetDlgItemTextA(hwnd, IDC_EDIT_FIRSTNAME, buffer, MAX_STRING))
00742                                 {
00743                                         gCmdLineFirstName = buffer;
00744                                 }
00745                                 if (GetDlgItemTextA(hwnd, IDC_EDIT_LASTNAME, buffer, MAX_STRING))
00746                                 {
00747                                         gCmdLineLastName = buffer;
00748                                 }
00749                                 if (GetDlgItemTextA(hwnd, IDC_EDIT_PASSWORD, buffer, MAX_STRING))
00750                                 {
00751                                         gCmdLinePassword = buffer;
00752                                 }
00753                                 BOOL remember_password = (IsDlgButtonChecked(hwnd, IDC_REMEMBER_PASSWORD) == BST_CHECKED);
00754                                 gSavedSettings.setBOOL("RememberPassword", remember_password);
00755                                 EndDialog(hwnd, 0);     
00756                                 return TRUE;    
00757                         }
00758                 }
00759                 
00760                 return FALSE;
00761 
00762         case WM_CLOSE:
00763         case WM_DESTROY:
00764                 EndDialog(hwnd, 666);   
00765                 return TRUE;    
00766 
00767         default:
00768                 return FALSE;
00769         }
00770 }
00771 #endif
00772 
00773 #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
00774 
00775 MEM_BOOL MEM_CALLBACK second_mem_error_handler(MEM_ERROR_INFO *errorInfo);
00776 
00777 MEM_BOOL MEM_CALLBACK first_mem_error_handler(MEM_ERROR_INFO *errorInfo)
00778 {
00779     MemSetErrorHandler(second_mem_error_handler);
00780 
00781         
00782         
00783         
00784 
00785         llerrs << "Memory allocation failed; aborting." << llendl;
00786         
00787 
00788         
00789         
00790         
00791         return 0;
00792 }
00793 
00794 MEM_BOOL MEM_CALLBACK second_mem_error_handler(MEM_ERROR_INFO *errorInfo)
00795 {
00796         
00797         LLError::crashAndLoop("");
00798         
00799         return 0;
00800 }
00801 
00802 #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
00803 
00804 
00805 #if LL_WINDOWS
00806 int APIENTRY WinMain(HINSTANCE hInstance,
00807                      HINSTANCE hPrevInstance,
00808                      LPSTR     lpCmdLine,
00809                      int       nCmdShow)
00810 #else 
00811 int main( int argc, char **argv ) 
00812 #endif
00813 {
00814         LLMemType mt1(LLMemType::MTYPE_STARTUP);
00815 
00816 #if LL_SOLARIS && defined(__sparc)
00817         asm ("ta\t6");           
00818 #endif
00819 
00820 #if LL_DARWIN
00821         
00822         (void) chdir(gDirUtilp->getAppRODataDir().c_str());
00823 #endif
00824         
00825 #if 1
00826         
00827         LLCommon::initClass();
00828         
00829 # if MEM_TRACK_MEM
00830         static const bool enable_threads = false;
00831 # else
00832         static const bool enable_threads = true;
00833 # endif
00834         LLVFSThread::initClass(enable_threads && true);
00835         LLLFSThread::initClass(enable_threads && true);
00836         
00837         gImageDecodeThread = new LLWorkerThread("ImageDecode", enable_threads && true);
00838         gTextureCache = new LLTextureCache(enable_threads && true);
00839         gTextureFetch = new LLTextureFetch(gTextureCache, enable_threads && false);
00840         LLImageWorker::initClass(gImageDecodeThread);
00841         LLImageJ2C::openDSO();
00842 #endif
00843 
00844 #if LL_WINDOWS
00845         
00846         
00847         
00848         
00849         
00850         
00851         LPSTR cmd_line_including_exe_name = GetCommandLineA();
00852 
00853         gIconResource = MAKEINTRESOURCE(IDI_LL_ICON);
00854 
00855         const S32       MAX_ARGS = 100;
00856         int argc = 0;
00857         char* argv[MAX_ARGS];           
00858 
00859         char *token = NULL;
00860         if( cmd_line_including_exe_name[0] == '\"' )
00861         {
00862                 
00863                 token = strtok( cmd_line_including_exe_name, "\"" );
00864                 argv[argc++] = token;
00865                 token = strtok( NULL, " \t," );
00866         }
00867         else
00868         {
00869                 
00870                 token = strtok( cmd_line_including_exe_name, " \t," );
00871         }
00872 
00873         while( (token != NULL) && (argc < MAX_ARGS) )
00874         {
00875                 argv[argc++] = token;
00876                 
00877                 if (*(token + strlen(token) + 1) == '\"')               
00878                 {
00879                         token = strtok( NULL, "\"");
00880                 }
00881                 else
00882                 {
00883                         token = strtok( NULL, " \t," );
00884                 }
00885         }
00886 #endif
00887 
00888         
00889         
00890         
00891         
00892         
00893         
00894         
00895         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[UserServerDefaultChoice].mName);              
00896         S32 j;
00897         for (j = 1; j < argc; j++) 
00898         {
00899                 if (!strcmp(argv[j], "--aditi"))
00900                 {
00901                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_ADITI].mName);             
00902                 }
00903                 else if (!strcmp(argv[j], "--agni"))
00904                 {
00905                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_AGNI].mName);              
00906                 }
00907                 else if (!strcmp(argv[j], "--dmz"))
00908                 {
00909                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_DMZ].mName);               
00910                 }
00911                 else if (!strcmp(argv[j], "--siva"))
00912                 {
00913                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_SIVA].mName);              
00914                 }
00915                 else if (!strcmp(argv[j], "--shakti"))
00916                 {
00917                         sprintf(gUserServerName,"%s", gUserServerDomainName[USERSERVER_SHAKTI].mName);
00918                 }
00919                 else if (!strcmp(argv[j], "--durga"))
00920                 {
00921                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_DURGA].mName);             
00922                 }
00923                 else if (!strcmp(argv[j], "--soma"))
00924                 {
00925                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_SOMA].mName);              
00926                 }
00927                 else if (!strcmp(argv[j], "--ganga"))
00928                 {
00929                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[USERSERVER_GANGA].mName);             
00930                 }
00931                 else if (!strcmp(argv[j], "--vaak"))
00932                 {
00933                         sprintf(gUserServerName,"%s", gUserServerDomainName[USERSERVER_VAAK].mName);
00934                 }
00935                 else if (!strcmp(argv[j], "--uma"))
00936                 {
00937                         sprintf(gUserServerName,"%s", gUserServerDomainName[USERSERVER_UMA].mName);
00938                 }
00939                 else if (!strcmp(argv[j], "-user") && (++j < argc))
00940                 {
00941                         if (!strcmp(argv[j], "-"))
00942                         {
00943                                 snprintf(gUserServerName, MAX_STRING, "%s", LOOPBACK_ADDRESS_STRING);           
00944                         }
00945                         else
00946                         {
00947                                 snprintf(gUserServerName, MAX_STRING, "%s", argv[j]);           
00948                         }
00949                 }
00950                 else if (!strcmp(argv[j], "-multiple"))
00951                 {
00952                         
00953                         gMultipleViewersOK = TRUE;
00954                 }
00955                 else if (!strcmp(argv[j], "-novoice"))
00956                 {
00957                         
00958                         gDisableVoice = TRUE;
00959                 }
00960         }
00961 
00962         
00963         
00964         
00965         
00966         
00967         
00968         
00969 
00970         
00971         
00972         gDirUtilp->initAppDirs("SecondLife");
00973 
00974         
00975         
00976         
00977         LLError::initForApplication(
00978                                 gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
00979         LLError::setFatalFunction(errorCallback);
00980 
00981 
00982 #if LL_RELEASE_FOR_DOWNLOAD && LL_SEND_CRASH_REPORTS
00983         
00984         
00985         
00986         
00987         init_crash_handler();
00988 #endif
00989         
00990         init_logging();
00991         
00992         
00993         
00994         
00995 
00996         
00997         gSettingsFileName = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, DEFAULT_SETTINGS_FILE);
00998         gOldSettingsFileName = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, LEGACY_DEFAULT_SETTINGS_FILE);
00999 
01001         
01002         
01003         
01004         S32 args_result = 0;
01005 
01006 #if LL_DARWIN
01007         {
01008                 
01009                 std::string args;
01010                 if(_read_file_into_string(args, "arguments.txt"))
01011                 {
01012                         
01013                         
01014                         
01015                         std::vector<std::string> arglist;
01016                         
01017                         arglist.push_back("newview");
01018                         
01019                         llinfos << "Reading additional command line arguments from arguments.txt..." << llendl;
01020                         
01021                         typedef boost::tokenizer<boost::escaped_list_separator<char> > tokenizer;
01022                         boost::escaped_list_separator<char> sep("\\", "\r\n ", "\"'");
01023                         tokenizer tokens(args, sep);
01024                         tokenizer::iterator token_iter;
01025 
01026                         for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
01027                         {
01028                                 llinfos << "argument: '" << (token_iter->c_str()) << "'" << llendl;
01029                                 
01030                                 arglist.push_back(*token_iter);
01031                         }
01032 
01033                         char **fakeargv = new char*[arglist.size()];
01034                         int i;
01035                         for(i=0; i < arglist.size(); i++)
01036                                 fakeargv[i] = const_cast<char*>(arglist[i].c_str());
01037                                 
01038                         args_result = parse_args(arglist.size(), fakeargv);
01039                         delete[] fakeargv;
01040                 }
01041                 
01042                 
01043                 
01044                         
01045                         
01046                         
01047                         
01048                         
01049                         
01050                 CFURLRef url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("language"), CFSTR("txt"), NULL);
01051                 char path[MAX_PATH];
01052                 if(CFURLGetFileSystemRepresentation(url, false, (UInt8 *)path, sizeof(path)))
01053                 {
01054                         std::string lang;
01055                         if(_read_file_into_string(lang, path))
01056                         {
01057                                 gCommandLineForcedSettings["SystemLanguage"] = lang;
01058                         }
01059                 }
01060                 CFRelease(url);
01061         }
01062 #endif
01063 
01064         
01065         
01066         
01067         args_result |= parse_args(argc, argv);
01068         if (args_result)
01069         {
01070                 remove_marker_file();
01071                 return args_result;
01072         }
01073 
01074         if (!strcmp(gUserServerName, gUserServerDomainName[USERSERVER_AGNI].mName))
01075         {
01076                 gInProductionGrid = TRUE;
01077         }
01078 
01079         
01080         gSecondLife = "Second Life (Dale's Unofficial Viewer)";
01081         
01082         
01083         if (! gDirUtilp->getSkinDir().empty() )
01084         {
01085                 std::string skin_def_file = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, "skin.xml");
01086                 LLXmlTree skin_def_tree;
01087 
01088                 if (!skin_def_tree.parseFile(skin_def_file))
01089                 {
01090                         llerrs << "Failed to parse skin definition." << llendl;
01091                 }
01092 
01093                 LLXmlTreeNode* rootp = skin_def_tree.getRoot();
01094                 LLXmlTreeNode* disabled_message_node = rootp->getChildByName("disabled_message");       
01095                 if (disabled_message_node)
01096                 {
01097                         gDisabledMessage = disabled_message_node->getContents();
01098                 }
01099 
01100                 static LLStdStringHandle hide_links_string = LLXmlTree::addAttributeString("hide_links");
01101                 rootp->getFastAttributeBOOL(hide_links_string, gHideLinks);
01102 
01103                 
01104                 
01105                 static LLStdStringHandle silent_string = LLXmlTree::addAttributeString("silent_update");
01106                 BOOL silent_update;
01107                 rootp->getFastAttributeBOOL(silent_string, silent_update);
01108                 gHideLinks = (gHideLinks || silent_update);
01109         }
01110 
01111 #if LL_DARWIN
01112         
01113         init_apple_menu(gSecondLife.c_str());
01114 
01115 #if __ppc__
01116         
01117         
01118         if(!gSysCPU.hasAltivec())
01119         {
01120                 std::ostringstream msg;
01121                 msg << gSecondLife << " requires a processor with AltiVec (G4 or later).";
01122                 OSMessageBox(
01123                         msg.str().c_str(),
01124                         NULL,
01125                         OSMB_OK);
01126                 remove_marker_file();
01127                 return 1;
01128         }
01129 #endif
01130         
01131 #endif // LL_DARWIN
01132 
01133         
01134         
01135         std::ostringstream splash_msg;
01136         
01137         splash_msg << "Loading " << gSecondLife << "...";
01138         LLSplashScreen::show();
01139         LLSplashScreen::update(splash_msg.str().c_str());
01140 
01141         LLVolumeMgr::initClass();
01142 
01143         
01144         
01145         
01146         gFeatureManagerp = new LLFeatureManager;
01147 
01148         gStartTime = totalTime();
01149 
01150 
01152         
01153         
01154         
01155 
01156         
01157         declare_settings();
01158 
01159 #if !LL_RELEASE_FOR_DOWNLOAD
01160 
01161         gSavedSettings.saveToFile(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings_default.xml").c_str(), FALSE);
01162 #endif
01163 
01164         
01165         
01166         
01167 #if LL_RELEASE_FOR_DOWNLOAD
01168         gWindowTitle = gSecondLife;
01169 #elif LL_DEBUG
01170         gWindowTitle = gSecondLife + LLString(" [DEBUG] ") + gArgs;
01171 #else
01172         gWindowTitle = gSecondLife + LLString(" ") + gArgs;
01173 #endif
01174         LLString::truncate(gWindowTitle, 255);
01175 
01176         if (!gMultipleViewersOK)
01177         {
01178             
01179             
01180             
01181 
01182                 
01183                 
01184                 
01185                 
01186                 std::string slurl;
01187                 if (!LLStartUp::sSLURLCommand.empty())
01188                 {
01189                         slurl = LLStartUp::sSLURLCommand;
01190                 }
01191                 else if (LLURLSimString::parse())
01192                 {
01193                         slurl = LLURLSimString::getURL();
01194                 }
01195                 if (!slurl.empty())
01196                 {
01197                         if (send_url_to_other_instance(slurl))
01198                         {
01199                                 
01200                                 return 1;
01201                         }
01202                 }
01203                 
01204                 gSecondInstance = another_instance_running();
01205                 
01206                 if (gSecondInstance)
01207                 {
01208                         std::ostringstream msg;
01209                         msg << 
01210                                 gSecondLife << " is already running.\n"
01211                                 "\n"
01212                                 "Check your task bar for a minimized copy of the program.\n"
01213                                 "If this message persists, restart your computer.",
01214                         OSMessageBox(
01215                                 msg.str().c_str(),
01216                                 NULL,
01217                                 OSMB_OK);
01218                         return 1;
01219                 }
01220 
01221                 init_marker_file();
01222 
01223 #if LL_SEND_CRASH_REPORTS
01224                 if (gLastExecFroze)
01225                 {
01226                         llinfos << "Last execution froze, requesting to send crash report." << llendl;
01227                         
01228                         
01229                         
01230                         std::ostringstream msg;
01231                         msg << gSecondLife
01232                                 << " appears to have frozen or crashed on the previous run.\n"
01233                                 << "Would you like to send a crash report?";
01234                         std::string alert;
01235                         alert = gSecondLife;
01236                         alert += " Alert";
01237                         S32 choice = OSMessageBox(msg.str().c_str(),
01238                                 alert.c_str(),
01239                                 OSMB_YESNO);
01240                         if (OSBTN_YES == choice)
01241                         {
01242                                 llinfos << "Sending crash report." << llendl;
01243 
01244                                 remove_marker_file();
01245 #if LL_WINDOWS
01246                                 std::string exe_path = gDirUtilp->getAppRODataDir();
01247                                 exe_path += gDirUtilp->getDirDelimiter();
01248                                 exe_path += "win_crash_logger.exe";
01249 
01250                                 std::string arg_string = "-previous -user ";
01251                                 arg_string += gUserServerName;
01252                                 arg_string += " -name \"";
01253                                 arg_string += gSecondLife;
01254                                 arg_string += "\"";
01255                                 
01256                                 
01257                                 _spawnl(_P_WAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
01258 #elif LL_DARWIN
01259                                 std::string command_str;
01260                                 command_str = "crashreporter.app/Contents/MacOS/crashreporter ";
01261                                 command_str += "-previous -user ";
01262                                 command_str += gUserServerName;
01263                                 
01264                                 
01265                                 system(command_str.c_str());            
01266 #elif LL_LINUX || LL_SOLARIS
01267                                 std::string cmd =gDirUtilp->getAppRODataDir();
01268                                 cmd += gDirUtilp->getDirDelimiter();
01269 #if LL_LINUX
01270                                 cmd += "linux-crash-logger.bin";
01271 #else // LL_SOLARIS
01272                                 cmd += "bin/solaris-crash-logger";
01273 #endif
01274                                 char* const cmdargv[] =
01275                                         {(char*)cmd.c_str(),
01276                                          (char*)"-previous",
01277                                          (char*)"-user",
01278                                          (char*)gUserServerName,
01279                                          (char*)"-name",
01280                                          (char*)gSecondLife.c_str(),
01281                                          NULL};
01282                                 fflush(NULL);
01283                                 pid_t pid = fork();
01284                                 if (pid == 0)
01285                                 { 
01286                                         execv(cmd.c_str(), cmdargv);            
01287                                         llwarns << "execv failure when trying to start " << cmd << llendl;
01288                                         _exit(1); 
01289                                 } else {
01290                                         if (pid > 0)
01291                                         {
01292                                                 
01293                                                 int childExitStatus;
01294                                                 waitpid(pid, &childExitStatus, 0);
01295                                         } else {
01296                                                 llwarns << "fork failure." << llendl;
01297                                         }
01298                                 }
01299 #endif
01300                         }
01301                         else
01302                         {
01303                                 llinfos << "Not sending crash report." << llendl;
01304                         }
01305                 }
01306 #endif // #if LL_SEND_CRASH_REPORTS
01307         }
01308         else
01309         {
01310                 gSecondInstance = another_instance_running();
01311                 
01312                 if (gSecondInstance)
01313                 {
01314                         gDisableVoice = TRUE;
01315                 }
01316 
01317                 init_marker_file();
01318         }
01319 
01320         
01321         
01322         
01323         write_system_info();
01324 
01325 #if LL_WINDOWS
01326         
01327         
01328         
01329         
01330         
01331         llinfos << "Turning off Windows error reporting." << llendl;
01332         disable_win_error_reporting();
01333 #endif  // LL_WINDOWS
01334 
01335         
01336         gCurrentVersion = llformat("%s %d.%d.%d.%d.%d", gChannelName.c_str(), LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VERSION_BUILD, LL_VERSION_REVISION );
01337         
01338         
01339         
01340         
01341         llinfos << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << llendl;
01342 
01343         
01344         
01345         
01346         llinfos << "Loading feature tables." << llendl;
01347         
01348         gFeatureManagerp->loadFeatureTables();
01349         gFeatureManagerp->initCPUFeatureMasks();
01350 
01351         
01352         gSavedSettings.applyOverrides(gCommandLineSettings);
01353 
01354         
01355         gUICtrlFactory = new LLViewerUICtrlFactory();
01356         
01357         
01358         
01359         LLAlertDialog::parseAlerts("alerts.xml", &gSavedSettings, TRUE);
01360         
01361         
01362         llinfos << "Loading configuration file " << gSettingsFileName << llendl;
01363         if (0 == gSavedSettings.loadFromFile(gSettingsFileName))
01364         {
01365                 llinfos << "Failed to load settings from " << gSettingsFileName << llendl;
01366                 llinfos << "Loading legacy settings from " << gOldSettingsFileName << llendl;
01367                 gSavedSettings.loadFromFileLegacy(gOldSettingsFileName);
01368         }
01369 
01370         
01371         LLString nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
01372         if ( nextLoginLocation.length() )
01373         {
01374                 LLURLSimString::setString( nextLoginLocation.c_str() );
01375         };
01376 
01377         
01378         gSavedSettings.applyOverrides(gCommandLineForcedSettings);
01379 
01380         gLastRunVersion = gSavedSettings.getString("LastRunVersion");
01381 
01382         fixup_settings();
01383         
01384         
01385         std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
01386         gCrashSettings.loadFromFile(crash_settings_filename.c_str());
01387 
01389         
01391 #if LL_WINDOWS
01392         
01393 
01394 
01395 
01396 
01397 
01398 
01399 
01400 
01401 
01402 
01403 
01404 
01405 
01406 
01407 
01408 
01409 #endif
01410 
01411         
01412         gNumSessions = gSavedSettings.getS32("NumSessions");
01413         gNumSessions++;
01414         gSavedSettings.setS32("NumSessions", gNumSessions);
01415 
01416         gSavedSettings.setString("HelpLastVisitedURL",gSavedSettings.getString("HelpHomeURL"));
01417 
01418         if (gSavedSettings.getBOOL("VerboseLogs"))
01419         {
01420                 LLError::setPrintLocation(true);
01421         }
01422 
01423 #if !LL_RELEASE_FOR_DOWNLOAD
01424         if (gUserServerChoice == USERSERVER_NONE)
01425         {
01426                 
01427                 
01428                 S32 server = gSavedSettings.getS32("ServerChoice");
01429                 if (server != 0)
01430                         gUserServerChoice = (EUserServerDomain)llclamp(server, 0, (S32)USERSERVER_COUNT - 1);
01431                 if (server == USERSERVER_OTHER)
01432                 {
01433                         LLString custom_server = gSavedSettings.getString("CustomServer");
01434                         if (custom_server.empty())
01435                         {
01436                                 snprintf(gUserServerName, MAX_STRING, "none");          
01437                         }
01438                         else
01439                         {
01440                                 snprintf(gUserServerName, MAX_STRING, "%s", custom_server.c_str());             
01441                         }
01442                 }
01443         }
01444 #endif
01445 
01446         if (gUserServerChoice == USERSERVER_NONE)
01447         {
01448                 gUserServerChoice = UserServerDefaultChoice;
01449         }
01450         
01451         
01452         LLString viewer_art_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"viewerart.xml");
01453         llinfos << "Loading art table from " << viewer_art_filename << llendl;
01454         gViewerArt.loadFromFile(viewer_art_filename.c_str(), FALSE);
01455         LLString textures_filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "textures", "textures.xml");
01456         llinfos << "Loading art table from " << textures_filename << llendl;
01457         gViewerArt.loadFromFile(textures_filename.c_str(), FALSE);
01458 
01459         LLString colors_base_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "colors_base.xml");
01460         llinfos << "Loading base colors from " << colors_base_filename << llendl;
01461         gColors.loadFromFile(colors_base_filename.c_str(), FALSE, TYPE_COL4U);
01462 
01463         
01464         LLString user_colors_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "colors.xml");
01465         llinfos << "Loading user colors from " << user_colors_filename << llendl;
01466         if (gColors.loadFromFile(user_colors_filename.c_str(), FALSE, TYPE_COL4U) == 0)
01467         {
01468                 llinfos << "Failed to load user colors from " << user_colors_filename << llendl;
01469                 LLString user_legacy_colors_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "colors.ini");
01470                 llinfos << "Loading legacy colors from " << user_legacy_colors_filename << llendl;
01471                 gColors.loadFromFileLegacy(user_legacy_colors_filename.c_str(), FALSE, TYPE_COL4U);
01472         }
01473 
01474         
01475         LLUI::initClass(&gSavedSettings, 
01476                                         &gColors, 
01477                                         &gViewerArt,
01478                                         &gImageList,
01479                                         ui_audio_callback,
01480                                         &LLUI::sGLScaleFactor);
01481 
01482         gUICtrlFactory->setupPaths(); 
01483         
01485         
01486         
01487         
01488         
01489         LLGroupMgr::parseRoleActions("role_actions.xml");
01490 
01491         LLAgent::parseTeleportMessages("teleport_strings.xml");
01492 
01493         
01494         saved_settings_to_globals();
01495 
01496         
01497         
01498         
01499 
01500 
01501 
01502 
01503 
01504 
01505 
01506 
01507 
01508 
01509 
01510 
01511 
01512 
01513 
01514 
01515 
01516 
01517 
01518 
01519 
01520 
01521 
01522 
01523 
01524 
01525 
01526 
01527 
01528         
01529         gSerialNumber = get_serial_number();
01530 
01531 #if LL_WINDOWS
01532         
01533         
01534         
01535         
01536         if (gProbeHardware)
01537         {
01538                 BOOL vram_only = !gSavedSettings.getBOOL("ProbeHardwareOnStartup");
01539 
01540                 LLSplashScreen::update("Detecting hardware...");
01541 
01542                 llinfos << "Attempting to poll DirectX for hardware info" << llendl;
01543                 gDXHardware.setWriteDebugFunc(write_debug);
01544                 BOOL probe_ok = gDXHardware.getInfo(vram_only);
01545 
01546                 if (!probe_ok
01547                         && gSavedSettings.getWarning("AboutDirectX9"))
01548                 {
01549                         llinfos << "DirectX probe failed, alerting user." << llendl;
01550 
01551                         
01552                         
01553                         std::ostringstream msg;
01554                         msg << 
01555                                 gSecondLife << " is unable to detect DirectX 9.0b or greater.\n"
01556                                 "\n" <<
01557                                 gSecondLife << " uses DirectX to detect hardware and/or\n"
01558                                 "outdated drivers that can cause stability problems,\n"
01559                                 "poor performance and crashes.  While you can run\n" <<
01560                                 gSecondLife << " without it, we highly recommend running\n"
01561                                 "with DirectX 9.0b\n"
01562                                 "\n"
01563                                 "Do you wish to continue?\n";
01564                         S32 button = OSMessageBox(
01565                                 msg.str().c_str(),
01566                                 "Warning",
01567                                 OSMB_YESNO);
01568                         if (OSBTN_NO== button)
01569                         {
01570                                 llinfos << "User quitting after failed DirectX 9 detection" << llendl;
01571                                 LLWeb::loadURLExternal(DIRECTX_9_URL);
01572                                 return 0;
01573                         }
01574                         gSavedSettings.setWarning("AboutDirectX9", FALSE);
01575                 }
01576                 llinfos << "Done polling DirectX for hardware info" << llendl;
01577 
01578                 
01579                 gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
01580 
01581                 
01582                 LLSplashScreen::update(splash_msg.str().c_str());
01583         }
01584 
01585         if (!LLWinDebug::setupExceptionHandler())
01586         {
01587                 llwarns << " Someone took over my exception handler (post hardware probe)!" << llendl;
01588         }
01589 
01590         gGLManager.mVRAM = gDXHardware.getVRAM();
01591         llinfos << "Detected VRAM: " << gGLManager.mVRAM << llendl;
01592 #endif
01593 
01594         
01595         
01596         LLUUID::getNodeID(gMACAddress);
01597 
01598         
01599         
01600 #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
01601         MemSetErrorHandler(first_mem_error_handler);
01602 #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
01603 
01604         gViewerStats = new LLViewerStats();
01605 
01606         
01607         
01608         
01609 
01610         if (!init_cache())
01611         {
01612                 std::ostringstream msg;
01613                 msg <<
01614                         gSecondLife << " is unable to access a file that it needs.\n"
01615                         "\n"
01616                         "This can be because you somehow have multiple copies running, "
01617                         "or your system incorrectly thinks a file is open. "
01618                         "If this message persists, restart your computer and try again. "
01619                         "If it continues to persist, you may need to completely uninstall " <<
01620                         gSecondLife << " and reinstall it.";
01621                 OSMessageBox(
01622                         msg.str().c_str(),
01623                         NULL,
01624                         OSMB_OK);
01625                 return 1;
01626         }
01627         
01628 #if LL_DARWIN
01629         
01630         if(!gHideLinks && gCurrentVersion != gLastRunVersion)
01631         {
01632                 
01633                 DisplayReleaseNotes();
01634         }
01635 #endif
01636 
01637         
01638         
01639         
01640 
01641         
01642 #if LL_WINDOWS
01643         if (gUseConsole && gSavedSettings.getBOOL("ShowConsoleWindow"))
01644         {
01645                 create_console();
01646         }
01647 #endif
01648 
01649         llinfos << "Initializing window..." << llendl;
01650 
01651         
01652         gNoRender = gSavedSettings.getBOOL("DisableRendering");
01653 
01654         
01655         LLSplashScreen::hide();
01656 
01657         
01658         char window_title_str[256];             
01659         strncpy(window_title_str, gWindowTitle.c_str(), sizeof(window_title_str) - 1);          
01660         window_title_str[sizeof(window_title_str) - 1] = '\0';
01661 
01662         
01663         gViewerWindow = new LLViewerWindow(window_title_str, sWindowClass,
01664                 gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
01665                 gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
01666                 FALSE, gIgnorePixelDepth, gSavedSettings.getS32("StereoMode"));
01667                 
01668         if (gSavedSettings.getBOOL("FullScreen"))
01669         {
01670                 gViewerWindow->toggleFullscreen(FALSE);
01671                         
01672         }
01673 
01674         
01675         gSavedSettings.setS32("StereoMode", gViewerWindow->getWindow()->getStereoMode());
01676 
01677         if (gSavedSettings.getBOOL("WindowMaximized"))
01678         {
01679                 gViewerWindow->mWindow->maximize();
01680                 gViewerWindow->getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
01681         }
01682 
01683         LLUI::sWindow = gViewerWindow->getWindow();
01684 
01685         LLAlertDialog::parseAlerts("alerts.xml");
01686         LLNotifyBox::parseNotify("notify.xml");
01687 
01688         LLMediaEngine::initClass();
01689         
01690         
01691         
01692         
01693         
01694         gFeatureManagerp->cleanupFeatureTables();
01695 
01696         
01697         gViewerWindow->setCursor(UI_CURSOR_WAIT);
01698 
01699         
01700 #if LL_WINDOWS && LL_LCD_COMPILE
01701         
01702         gLcdScreen = new llLCD(hInstance);
01703         CreateLCDDebugWindows();
01704 #endif
01705 
01706         
01707         gViewerWindow->initBase();
01708 
01709         
01710         gViewerWindow->mWindow->show();
01711 
01712         write_debug(gGLManager.getGLInfoString());
01713         llinfos << gGLManager.getGLInfoString() << llendl;
01714 
01715         
01716         bind_keyboard_functions();
01717 
01718         
01719         if (!gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keys.ini").c_str()))
01720         {
01721                 llerrs << "Unable to open keys.ini" << llendl;
01722         }
01723         
01724         gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"custom_keys.ini").c_str());
01725 
01726         
01727         FILE* app_file = LLFile::fopen( gDirUtilp->getExecutablePathAndName().c_str(), "rb" );          
01728         if( app_file )
01729         {
01730                 LLMD5 app_md5;
01731                 app_md5.update( app_file ); 
01732                 app_md5.finalize();
01733                 app_md5.raw_digest( gViewerDigest.mData );
01734         }
01735         llinfos << "Viewer Digest: " << gViewerDigest << llendl;
01736 
01737         
01738         
01739         if (!gGLManager.mHasMultitexture && !gNoRender)
01740         {
01741                 std::ostringstream msg;
01742                 msg <<
01743                         "You do not appear to have the proper hardware requirements "
01744                         "for " << gSecondLife << ". " << gSecondLife << " requires an OpenGL graphics "
01745                         "card that has multitexture support. If this is the case, "
01746                         "you may want to make sure that you have the latest drivers for "
01747                         "your graphics card, and service packs and patches for your "
01748                         "operating system.\n"
01749                         "If you continue to have problems, please go to: "
01750                         "www.secondlife.com/support ";
01751                 OSMessageBox(
01752                         msg.str().c_str(),
01753                         NULL,
01754                         OSMB_OK);
01755                 return 0;
01756         }
01757 
01758         
01759         gSavedSettings.setString("LastRunVersion", gCurrentVersion);
01760 
01761         gSimLastTime = gRenderStartTime.getElapsedTimeF32();
01762         gSimFrames   = (F32)gFrameCount;
01763 
01764         
01765         
01766         
01767         main_loop();
01768 
01769         cleanup_app();
01770 
01771         
01772         
01773         if (!gLaunchFileOnQuit.empty())
01774         {
01775 #if LL_WINDOWS
01776                 
01777                 SetCursor(LoadCursor(NULL, IDC_WAIT));
01778 #endif
01779 
01780                 
01781                 ms_sleep(1000);
01782 
01783                 LLWeb::loadURLExternal( gLaunchFileOnQuit );
01784         }
01785 
01786         llinfos << "Goodbye" << llendflush;
01787         return 0;
01788 }
01789 
01790 bool send_url_to_other_instance(const std::string& url)
01791 {
01792 #if LL_WINDOWS
01793         wchar_t window_class[256];    
01794         mbstowcs(window_class, sWindowClass, 255);
01795         window_class[255] = 0;
01796         
01797         HWND other_window = FindWindow(window_class, NULL);
01798         if (other_window != NULL)
01799         {
01800                 lldebugs << "Found other window with the name '" << gWindowTitle << "'" << llendl;
01801                 COPYDATASTRUCT cds;
01802                 const S32 SLURL_MESSAGE_TYPE = 0;
01803                 cds.dwData = SLURL_MESSAGE_TYPE;
01804                 cds.cbData = url.length() + 1;
01805                 cds.lpData = (void*)url.c_str();
01806 
01807                 LRESULT msg_result = SendMessage(other_window, WM_COPYDATA, NULL, (LPARAM)&cds);
01808                 lldebugs << "SendMessage(WM_COPYDATA) to other window '" 
01809                                  << gWindowTitle << "' returned " << msg_result << llendl;
01810                 return true;
01811         }
01812 #endif
01813         return false;
01814 }
01815 
01816 BOOL another_instance_running()
01817 {
01818         
01819         
01820 
01821         std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.exec_marker");
01822         llinfos << "Checking marker file for lock..." << llendl;
01823 
01824         
01825         
01826         FILE* fMarker = LLFile::fopen(marker_file.c_str(), "rb");               
01827         if (fMarker != NULL)
01828         {
01829                 
01830                 fclose(fMarker);
01831                 fMarker = LLFile::fopen(marker_file.c_str(), "wb");             
01832                 if (fMarker == NULL)
01833                 {
01834                         llinfos << "Marker file is locked." << llendl;
01835                         return TRUE;
01836                 }
01837 #if LL_DARWIN
01838                 
01839                 if (flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
01840                 {
01841                         
01842                         fclose(fMarker);
01843                         llinfos << "Marker file is locked." << llendl;
01844                         return TRUE;
01845                 }
01846 #endif
01847                 fclose(fMarker);
01848         }
01849         llinfos << "Marker file isn't locked." << llendl;
01850         return FALSE;
01851 }
01852 
01853 
01854 void check_for_events()
01855 {
01856         LLFastTimer t2(LLFastTimer::FTM_MESSAGES);
01857 #if LL_WINDOWS
01858         if (!LLWinDebug::setupExceptionHandler())
01859         {
01860                 llwarns << " Someone took over my exception handler (post messagehandling)!" << llendl;
01861         }
01862 #endif
01863 
01864         gViewerWindow->mWindow->gatherInput();
01865 }
01866 
01867 #include "moviemaker.h"
01868 extern BOOL gbCapturing;
01869 
01870 #if !LL_SOLARIS
01871 extern MovieMaker gMovieMaker;
01872 #endif
01873 
01874 void main_loop()
01875 {
01876         
01877         gServicePump = new LLPumpIO(gAPRPoolp);
01878         LLHTTPClient::setPump(*gServicePump);
01879         LLHTTPClient::setCABundle(gDirUtilp->getCAFile());
01880         
01881         
01882         gLocalSpeakerMgr = new LLLocalSpeakerMgr();
01883         gActiveChannelSpeakerMgr = new LLActiveSpeakerMgr();
01884 
01885         LLVoiceChannel::initClass();
01886         LLVoiceClient::init(gServicePump);
01887                                 
01888         LLMemType mt1(LLMemType::MTYPE_MAIN);
01889         LLTimer frameTimer,idleTimer;
01890         LLTimer debugTime;
01891         
01892         
01893         while (!gQuit)
01894         {
01895                 LLFastTimer::reset(); 
01896                 {
01897                         LLFastTimer t(LLFastTimer::FTM_FRAME);
01898 
01899                         check_for_events();
01900 
01901 #if 1 && !RELEASE_FOR_DOWNLOAD
01902                         
01903                         if (debugTime.getElapsedTimeF32() > 1.f)
01904                         {
01905                                 debugTime.reset();
01906                         }
01907 #endif
01908                         if (!gQuit)
01909                         {
01910                                 
01911                                 
01912                                 
01913                                 if (gViewerWindow->mWindow->getVisible() 
01914                                         && gViewerWindow->getActive()
01915                                         && !gViewerWindow->mWindow->getMinimized()
01916                                         && LLStartUp::getStartupState() == STATE_STARTED
01917                                         && !gViewerWindow->getShowProgress()
01918                                         && !gFocusMgr.focusLocked())
01919                                 {
01920                                         gKeyboard->scanKeyboard();
01921                                         LLViewerJoystick::scanJoystick();
01922                                 }
01923 
01924                                 
01925                                 {
01926                                         LLFastTimer t3(LLFastTimer::FTM_IDLE);
01927                                         idle();
01928                                         LLCurl::process();
01929                                         
01930                                         gServicePump->pump();
01931                                         gServicePump->callback();
01932                                 }
01933 
01934                                 if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
01935                                 {
01936                                         save_final_snapshot(NULL);
01937                                         disconnect_viewer(NULL);
01938                                 }
01939 
01940                                 
01941                                 if (!gQuit)
01942                                 {
01943                                         display();
01944 
01945                                         LLFloaterSnapshot::update(); 
01946                                         
01947 #if !LL_SOLARIS
01948                                         if (gbCapturing)
01949                                         {
01950                                                 gMovieMaker.Snap();
01951                                         }
01952 #endif
01953 #if LL_WINDOWS && LL_LCD_COMPILE
01954                                         
01955                                         gLcdScreen->UpdateDisplay();
01956 #endif
01957                                 }
01958                         }
01959 
01960                         
01961                         {
01962                                 LLFastTimer t2(LLFastTimer::FTM_SLEEP);
01963                                 bool run_multiple_threads = gSavedSettings.getBOOL("RunMultipleThreads");
01964 
01965                                 
01966                                 if(gYieldTime)
01967                                 {
01968                                         ms_sleep(gYieldMS);
01969                                 }
01970 
01971                                 
01972                                 if (   gNoRender
01973                                                 || !gViewerWindow->mWindow->getVisible()
01974                                                 || !gFocusMgr.getAppHasFocus())
01975                                 {
01976                                         
01977                                         S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
01978                                         
01979                                         
01980                                         if (milliseconds_to_sleep > 0)
01981                                         {
01982                                                 ms_sleep(milliseconds_to_sleep);
01983                                                 
01984                                                 gTextureCache->pause();
01985                                                 gImageDecodeThread->pause();
01986                                         }
01987                                 }
01988                                 
01989                                 if (gRandomizeFramerate)
01990                                 {
01991                                         ms_sleep(rand() % 200);
01992                                 }
01993 
01994                                 if (gPeriodicSlowFrame
01995                                         && (gFrameCount % 10 == 0))
01996                                 {
01997                                         llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
01998                                         ms_sleep(500);
01999                                 }
02000 
02001 
02002                                 const F64 min_frame_time = 0.0; 
02003                                 const F64 min_idle_time = 0.0; 
02004                                 const F64 max_idle_time = run_multiple_threads ? min_idle_time : .005; 
02005                                 idleTimer.reset();
02006                                 while(1)
02007                                 {
02008                                         S32 work_pending = 0;
02009                                         S32 io_pending = 0;
02010                                         work_pending += gTextureCache->update(1); 
02011                                         work_pending += gImageDecodeThread->update(1); 
02012                                         work_pending += gTextureFetch->update(1); 
02013                                         io_pending += LLVFSThread::updateClass(1);
02014                                         io_pending += LLLFSThread::updateClass(1);
02015                                         if (io_pending > 1000)
02016                                         {
02017                                                 ms_sleep(llmin(io_pending/100,100)); 
02018                                         }
02019 
02020                                         F64 frame_time = frameTimer.getElapsedTimeF64();
02021                                         F64 idle_time = idleTimer.getElapsedTimeF64();
02022                                         if (frame_time >= min_frame_time &&
02023                                                 idle_time >= min_idle_time &&
02024                                                 (!work_pending || idle_time >= max_idle_time))
02025                                         {
02026                                                 break;
02027                                         }
02028                                 }
02029                                 frameTimer.reset();
02030 
02031                                  
02032                                 
02033                                 if (run_multiple_threads == FALSE)
02034                                 {
02035                                         gTextureCache->pause();
02036                                         gImageDecodeThread->pause();
02037                                         
02038                                 }
02039                                 
02040                                 
02041                         }
02042                                                 
02043                 }
02044         }
02045 
02046         
02047         if (STATE_STARTED == LLStartUp::getStartupState())
02048         {
02049                 save_final_snapshot(NULL);
02050         }
02051         
02052         delete gServicePump;
02053 
02054         llinfos << "Exiting main_loop" << llendflush;
02055 }
02056 
02057 
02058 void process_keystrokes_async()
02059 {
02060 #if LL_WINDOWS
02061         MSG                     msg;
02062         
02063         while( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD))
02064         {
02065                 
02066                 if (msg.message >= WM_MOUSEFIRST && 
02067                         msg.message <= WM_MOUSELAST ||
02068                         msg.message == WM_QUIT)
02069                 {
02070                         break;
02071                 }
02072 
02073                 
02074                 PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE | PM_NOYIELD);
02075                 
02076                 
02077                 
02078                 
02079                 TranslateMessage(&msg);
02080                 DispatchMessage(&msg);
02081         }
02082 
02083         
02084         
02085         
02086         if (gViewerWindow->mWindow->getVisible() 
02087                 && gViewerWindow->getActive()
02088                 && !gViewerWindow->mWindow->getMinimized()
02089                 && LLStartUp::getStartupState() == STATE_STARTED
02090                 && !gViewerWindow->getShowProgress()
02091                 && !gFocusMgr.focusLocked())
02092         {
02093                 gKeyboard->scanKeyboard();
02094         }
02095 #endif
02096 }
02097 
02099 
02100 
02101 
02102 
02103 FILE *gMarkerFile = NULL;
02104 
02105 void remove_marker_file()
02106 {
02107         llinfos << "remove_marker_file()" << llendl;
02108         if (gMarkerFile != NULL)
02109         {
02110                 fclose(gMarkerFile);
02111                 gMarkerFile = NULL;
02112         }
02113         if( gDirUtilp )
02114         {
02115                 LLString marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.exec_marker");
02116                 ll_apr_file_remove( marker_file );
02117         }
02118 }
02119 
02120 void init_marker_file()
02121 {
02122 #if LL_SOLARIS
02123         struct flock fl;
02124         fl.l_whence = SEEK_SET;
02125         fl.l_start = 0;
02126         fl.l_len = 1;
02127 #endif
02128         
02129         
02130         
02131 
02132         std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.exec_marker");
02133         llinfos << "Checking marker file for lock..." << llendl;
02134 
02135         FILE* fMarker = LLFile::fopen(marker_file.c_str(), "rb");               
02136         if (fMarker != NULL)
02137         {
02138                 
02139                 fclose(fMarker);
02140                 fMarker = LLFile::fopen(marker_file.c_str(), "wb");             
02141                 if (fMarker == NULL)
02142                 {
02143                         
02144                         llinfos << "Marker file is locked." << llendl;
02145                         return;
02146                 }
02147 #if LL_DARWIN
02148                 
02149                 if (flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
02150                 {
02151                         
02152                         fclose(fMarker);
02153                         llinfos << "Marker file is locked." << llendl;
02154                         return;
02155                 }
02156 #endif
02157 
02158                 
02159                 fclose(fMarker);
02160                 gLastExecFroze = TRUE;
02161                 llinfos << "Exec marker found: program froze on previous execution" << llendl;
02162         }
02163 
02164         
02165 
02166 #if LL_WINDOWS
02167         gMarkerFile = LLFile::_fsopen(marker_file.c_str(), "w", _SH_DENYWR);
02168 #else
02169         gMarkerFile = LLFile::fopen(marker_file.c_str(), "w");          
02170         if (gMarkerFile)
02171         {
02172                 int fd = fileno(gMarkerFile);
02173                 
02174 #if LL_SOLARIS
02175                 fl.l_type = F_WRLCK;
02176                 if (fcntl(fd, F_SETLK, &fl) == -1)
02177 #else
02178                 if (flock(fd, LOCK_EX | LOCK_NB) == -1)
02179 #endif
02180                 {
02181                         llinfos << "Failed to lock file." << llendl;
02182                 }
02183         }
02184 #endif
02185         if (gMarkerFile)
02186         {
02187                 llinfos << "Marker file created." << llendl;
02188         }
02189         else
02190         {
02191                 llinfos << "Failed to create marker file." << llendl;
02192         }
02193 
02194 #if LL_WINDOWS
02195         
02196         llinfos << "Removing SecondLife.dmp" << llendl;
02197         std::string dmp_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.dmp");
02198         LLFile::remove(dmp_filename.c_str());
02199 #endif
02200 
02201         
02202         
02203         llinfos << "Removing message.log" << llendl;
02204         std::string message_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "message.log");
02205         LLFile::remove(message_filename.c_str());
02206 
02207         llinfos << "Exiting init_marker_file()." << llendl;
02208 }
02209 
02210 void init_crash_handler()
02211 {
02213         
02214         
02215         
02216 
02217         
02218         catch_signals();
02219 
02220         
02221         gCrashCallback = viewer_crash_callback;
02222 }
02223 
02224 void init_logging()
02225 {
02226         
02227         std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
02228                                                              "SecondLife.old");
02229         LLFile::remove(old_log_file.c_str());
02230 
02231 #if LL_LINUX || LL_SOLARIS
02232         
02233         std::string old_stack_file =
02234                 gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
02235         LLFile::remove(old_stack_file.c_str());
02236 #endif // LL_LINUX || LL_SOLARIS
02237 
02238         
02239         std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
02240                                                              "SecondLife.log");
02241         LLFile::rename(log_file.c_str(), old_log_file.c_str());
02242 
02243         
02244 
02245         LLError::logToFile(log_file);
02246 }
02247 
02248 void write_system_info()
02249 {
02250         write_debug("SL Log: ");
02251         write_debug(LLError::logFileName());
02252         write_debug("\n");
02253 
02254         std::string tmp_str = gSecondLife
02255                 + llformat(" version %d.%d.%d build %d",
02256                                    LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD);
02257         write_debug(tmp_str.c_str());
02258         write_debug("\n");
02259         write_debug(gSysCPU.getCPUString());
02260         write_debug("\n");
02261         
02262         tmp_str = llformat("RAM: %u KB\n", gSysMemory.getPhysicalMemoryKB());
02263         write_debug(tmp_str.c_str());
02264         write_debug("OS: ");
02265         write_debug(gSysOS.getOSString().c_str());
02266         write_debug("\n");
02267 
02268         
02269         llinfos << gSecondLife << " version "
02270                 << LL_VERSION_MAJOR << "."
02271                 << LL_VERSION_MINOR << "."
02272                 << LL_VERSION_PATCH
02273                 << llendl;
02274 
02275         
02276         time_t now;
02277         time(&now);
02278         char tbuffer[256];              
02279         strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
02280         llinfos << "Local time: " << tbuffer << llendl;
02281 
02282         
02283         llinfos << "CPU info:\n" << gSysCPU << llendl;
02284         llinfos << "Memory info:\n" << gSysMemory << llendl;
02285         llinfos << "OS info: " << gSysOS << llendl;
02286 }
02287 
02288 #if LL_WINDOWS
02289 void disable_win_error_reporting()
02290 {
02291         const char win_xp_string[] = "Microsoft Windows XP";
02292         BOOL is_win_xp = ( gSysOS.getOSString().substr(0, strlen(win_xp_string) ) == win_xp_string );           
02293         if( is_win_xp )
02294         {
02295                 
02296                 
02297                 HINSTANCE fault_rep_dll_handle = LoadLibrary(L"faultrep.dll");          
02298                 if( fault_rep_dll_handle )
02299                 {
02300                         pfn_ADDEREXCLUDEDAPPLICATIONA pAddERExcludedApplicationA  = (pfn_ADDEREXCLUDEDAPPLICATIONA) GetProcAddress(fault_rep_dll_handle, "AddERExcludedApplicationA");
02301                         if( pAddERExcludedApplicationA )
02302                         {
02303 
02304                                 
02305                                 const char* executable_name = gDirUtilp->getExecutableFilename().c_str();
02306 
02307                                 if( 0 == pAddERExcludedApplicationA( executable_name ) )
02308                                 {
02309                                         U32 error_code = GetLastError();
02310                                         llinfos << "AddERExcludedApplication() failed with error code " << error_code << llendl;
02311                                 }
02312                                 else
02313                                 {
02314                                         llinfos << "AddERExcludedApplication() success for " << executable_name << llendl;
02315                                 }
02316                         }
02317                         FreeLibrary( fault_rep_dll_handle );
02318                 }
02319         }
02320 }
02321 #endif  // LL_WINDOWS
02322 
02323 
02324 
02325 std::string get_serial_number()
02326 {
02327         char serial_md5[MD5HEX_STR_SIZE];               
02328         serial_md5[0] = 0;
02329 
02330 #if LL_WINDOWS
02331         DWORD serial = 0;
02332         DWORD flags = 0;
02333         BOOL success = GetVolumeInformation(
02334                         L"C:\\",
02335                         NULL,           
02336                         0,                      
02337                         &serial,        
02338                         NULL,           
02339                         &flags,         
02340                         NULL,           
02341                         0);                     
02342         if (success)
02343         {
02344                 LLMD5 md5;
02345                 md5.update( (unsigned char*)&serial, sizeof(DWORD));
02346                 md5.finalize();
02347                 md5.hex_digest(serial_md5);
02348         }
02349         else
02350         {
02351                 llwarns << "GetVolumeInformation failed" << llendl;
02352         }
02353         return serial_md5;
02354 
02355 #elif LL_DARWIN 
02356         
02357         CFStringRef serialNumber = NULL;
02358         io_service_t    platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
02359                                                                                                                                  IOServiceMatching("IOPlatformExpertDevice"));
02360         if (platformExpert) {
02361                 serialNumber = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,
02362                                                                                                                                          CFSTR(kIOPlatformSerialNumberKey),
02363                                                                                                                                          kCFAllocatorDefault, 0);               
02364                 IOObjectRelease(platformExpert);
02365         }
02366         
02367         if (serialNumber)
02368         {
02369                 char buffer[MAX_STRING];                
02370                 if (CFStringGetCString(serialNumber, buffer, MAX_STRING, kCFStringEncodingASCII))
02371                 {
02372                         LLMD5 md5( (unsigned char*)buffer );
02373                         md5.hex_digest(serial_md5);
02374                 }
02375                 CFRelease(serialNumber);
02376         }
02377 
02378         return serial_md5;
02379 
02380 #elif LL_LINUX || LL_SOLARIS
02381         
02382         return serial_md5;
02383 
02384 #endif
02385 }
02386 
02387 #if LL_LINUX
02388 #define MAX_STACK_TRACE_DEPTH 40
02389 
02390 
02391 static inline BOOL do_basic_glibc_backtrace()
02392 {
02393         void *array[MAX_STACK_TRACE_DEPTH];
02394         size_t size;
02395         char **strings;
02396         size_t i;
02397         BOOL success = FALSE;
02398 
02399         size = backtrace(array, MAX_STACK_TRACE_DEPTH);
02400         strings = backtrace_symbols(array, size);
02401 
02402         std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
02403         llinfos << "Opening stack trace file " << strace_filename << llendl;
02404         FILE* StraceFile = LLFile::fopen(strace_filename.c_str(), "w");         
02405         if (!StraceFile)
02406         {
02407                 llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl;
02408                 StraceFile = stderr;
02409         }
02410 
02411         if (size)
02412         {
02413                 for (i = 0; i < size; i++)
02414                         fputs((std::string(strings[i])+"\n").c_str(),
02415                               StraceFile);
02416 
02417                 success = TRUE;
02418         }
02419         
02420         if (StraceFile != stderr)
02421                 fclose(StraceFile);
02422 
02423         free (strings);
02424         return success;
02425 }
02426 
02427 #if LL_ELFBIN
02428 
02429 
02430 
02431 static inline BOOL do_elfio_glibc_backtrace()
02432 {
02433         void *array[MAX_STACK_TRACE_DEPTH];
02434         size_t btsize;
02435         char **strings;
02436         BOOL success = FALSE;
02437 
02438         std::string appfilename = gDirUtilp->getExecutablePathAndName();
02439 
02440         std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
02441         llinfos << "Opening stack trace file " << strace_filename << llendl;
02442         FILE* StraceFile = LLFile::fopen(strace_filename.c_str(), "w");         
02443         if (!StraceFile)
02444         {
02445                 llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl;
02446                 StraceFile = stderr;
02447         }
02448 
02449         
02450         btsize = backtrace(array, MAX_STACK_TRACE_DEPTH);
02451         strings = backtrace_symbols(array, btsize);
02452 
02453         
02454         IELFI* pReader;
02455         const IELFISection* pSec = NULL;
02456         IELFISymbolTable* pSymTbl = 0;
02457         if (ERR_ELFIO_NO_ERROR != ELFIO::GetInstance()->CreateELFI(&pReader) ||
02458             ERR_ELFIO_NO_ERROR != pReader->Load(appfilename.c_str()) ||
02459             
02460             NULL == (pSec = pReader->GetSection( ".symtab" )) ||
02461             ERR_ELFIO_NO_ERROR != pReader->CreateSectionReader(IELFI::ELFI_SYMBOL, pSec, (void**)&pSymTbl) )
02462         {
02463                 
02464                 llinfos << "Could not initialize ELF symbol reading - doing basic backtrace." << llendl;
02465                 if (StraceFile != stderr)
02466                         fclose(StraceFile);
02467                 
02468                 
02469                 
02470                 
02471                 return do_basic_glibc_backtrace();
02472         }
02473 
02474         
02475         std::string   name;
02476         Elf32_Addr    value;
02477         Elf32_Word    ssize;
02478         unsigned char bind;
02479         unsigned char type;
02480         Elf32_Half    section;
02481         int nSymNo = pSymTbl->GetSymbolNum();
02482         size_t btpos;
02483         for (btpos = 0; btpos < btsize; ++btpos)
02484         {
02485                 fprintf(StraceFile, "%d:\t", btpos);
02486                 int symidx;
02487                 for (symidx = 0; symidx < nSymNo; ++symidx)
02488                 {
02489                         if (ERR_ELFIO_NO_ERROR ==
02490                             pSymTbl->GetSymbol(symidx, name, value, ssize,
02491                                                bind, type, section))
02492                         {
02493                                 
02494                                 if (uintptr_t(array[btpos]) >= value &&
02495                                     uintptr_t(array[btpos]) < value+ssize)
02496                                 {
02497                                         char *demangled_str = NULL;
02498                                         int demangle_result = 1;
02499                                         demangled_str =
02500                                                 abi::__cxa_demangle
02501                                                 (name.c_str(), NULL, NULL,
02502                                                  &demangle_result);
02503                                         if (0 == demangle_result &&
02504                                             NULL != demangled_str) {
02505                                                 fprintf(StraceFile,
02506                                                         "ELF(%s", demangled_str);
02507                                                 free(demangled_str);
02508                                         }
02509                                         else 
02510                                         {
02511                                                 fprintf(StraceFile,
02512                                                         "ELF(%s", name.c_str());
02513                                         }
02514                                         
02515                                         fprintf(StraceFile,
02516                                                 "+0x%lx) [%p]\n",
02517                                                 uintptr_t(array[btpos]) -
02518                                                 value,
02519                                                 array[btpos]);
02520                                         goto got_sym; 
02521                                 }
02522                         }
02523                 }
02524                 
02525                 
02526                 
02527                 fprintf(StraceFile, "%s\n", strings[btpos]);
02528         got_sym:;
02529         }
02530         
02531         if (StraceFile != stderr)
02532                 fclose(StraceFile);
02533 
02534         pSymTbl->Release();
02535         pSec->Release();
02536         pReader->Release();
02537 
02538         free(strings);
02539 
02540         llinfos << "Finished generating stack trace." << llendl;
02541 
02542         success = TRUE;
02543         return success;
02544 }
02545 #endif // LL_ELFBIN
02546 #endif // LL_LINUX
02547 
02548 
02549 static inline bool being_debugged()
02550 {
02551         static enum {unknown, no, yes} debugged = unknown;
02552         
02553         if (debugged == unknown)
02554         {
02555 #if LL_LINUX
02556                 pid_t ppid = getppid();
02557                 char *name;
02558                 int ret;
02559 
02560                 ret = asprintf(&name, "/proc/%d/exe", ppid);
02561                 if (ret != -1)
02562                 {
02563                         char buf[1024];
02564                         ssize_t n;
02565                         
02566                         n = readlink(name, buf, sizeof(buf) - 1);
02567                         if (n != -1)
02568                         {
02569                                 char *base = strrchr(buf, '/');
02570                                 buf[n + 1] = '\0';
02571                                 if (base == NULL)
02572                                 {
02573                                         base = buf;
02574                                 } else {
02575                                         base += 1;
02576                                 }
02577                                 
02578                                 if (strcmp(base, "gdb") == 0)
02579                                 {
02580                                         debugged = yes;
02581                                 }
02582                         }
02583                         free(name);
02584                 }
02585 #endif // LL_LINUX
02586         }
02587 
02588         return debugged == yes;
02589 }
02590 
02591 #ifdef LL_SOLARIS
02592 static inline BOOL do_basic_glibc_backtrace()
02593 {
02594         BOOL success = FALSE;
02595 
02596         std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
02597         llinfos << "Opening stack trace file " << strace_filename << llendl;
02598         FILE* StraceFile = LLFile::fopen(strace_filename.c_str(), "w");
02599         if (!StraceFile)
02600         {
02601                 llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl;
02602                 StraceFile = stderr;
02603         }
02604 
02605         printstack(fileno(StraceFile));
02606 
02607         if (StraceFile != stderr)
02608                 fclose(StraceFile);
02609 
02610         return success;
02611 }
02612 #endif // LL_SOLARIS
02613 
02614 void viewer_crash_callback()
02615 {
02616         
02617         if (being_debugged())
02618         {
02619                 abort();
02620         }
02621 
02622         
02623         
02624         if (gReportedCrash)
02625         {
02626                 return;
02627         }
02628         gReportedCrash = TRUE;
02629 
02630         BOOL do_crash_report = FALSE;
02631 
02632         do_crash_report = TRUE;
02633 
02634         write_debug("Viewer exe: ");
02635         write_debug(gDirUtilp->getExecutablePathAndName().c_str());
02636         write_debug("\n");
02637         write_debug("Cur path: ");
02638         write_debug(gDirUtilp->getCurPath().c_str());
02639         write_debug("\n\n");
02640 
02641         if (gMessageSystem && gDirUtilp)
02642         {
02643                 std::string filename;
02644                 filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "stats.log");
02645                 llofstream file(filename.c_str(), llofstream::binary);
02646                 if(file.good())
02647                 {
02648                         gMessageSystem->summarizeLogs(file);
02649                 }
02650         }
02651 
02652         if (gMessageSystem)
02653         {
02654                 write_debug(gMessageSystem->getCircuitInfoString());
02655                 gMessageSystem->stopLogging();
02656         }
02657         write_debug("\n");
02658         if (gWorldp)
02659         {
02660                 write_debug(gWorldp->getInfoString());
02661         }
02662 
02663         
02664         close_debug();
02665         LLError::logToFile("");
02666 
02667         
02668 
02669         remove_marker_file();
02670 
02671 #if LL_WINDOWS
02672         
02673         std::string exe_path = gDirUtilp->getAppRODataDir();
02674         exe_path += gDirUtilp->getDirDelimiter();
02675         exe_path += "win_crash_logger.exe";
02676 
02677         std::string arg_string = "-user ";
02678         arg_string += gUserServerName;
02679 
02680         switch(gCrashBehavior)
02681         {
02682         case CRASH_BEHAVIOR_ASK:
02683         default:
02684                 arg_string += " -dialog ";
02685                 _spawnl(_P_NOWAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
02686                 break;
02687 
02688         case CRASH_BEHAVIOR_ALWAYS_SEND:
02689                 _spawnl(_P_NOWAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
02690                 break;
02691 
02692         case CRASH_BEHAVIOR_NEVER_SEND:
02693                 break;
02694         }
02695 
02696 #elif LL_DARWIN
02697         
02698         LLString command_str;
02699         command_str = "crashreporter.app/Contents/MacOS/crashreporter ";
02700         command_str += "-user ";
02701         command_str += gUserServerName;
02702         command_str += " &";    
02703         system(command_str.c_str());            
02704                 
02705         
02706         
02707         exit(1);
02708 #elif LL_LINUX || LL_SOLARIS
02709         
02710         
02711         if (CRASH_BEHAVIOR_NEVER_SEND != gCrashBehavior)
02712         {       
02713                 
02714 #  if LL_ELFBIN
02715                 do_elfio_glibc_backtrace(); 
02716 #  else
02717                 do_basic_glibc_backtrace(); 
02718 #  endif // LL_ELFBIN
02719                 
02720                 char* ask_dialog = "-dialog";
02721                 if (CRASH_BEHAVIOR_ASK != gCrashBehavior)
02722                         ask_dialog = ""; 
02723                 std::string cmd =gDirUtilp->getAppRODataDir();
02724                 cmd += gDirUtilp->getDirDelimiter();
02725                 cmd += "linux-crash-logger.bin";
02726                 char* const cmdargv[] =
02727                         {(char*)cmd.c_str(),
02728                          ask_dialog,
02729                          (char*)"-user",
02730                          (char*)gUserServerName,
02731                          (char*)"-name",
02732                          (char*)gSecondLife.c_str(),
02733                          NULL};
02734                 fflush(NULL);
02735                 pid_t pid = fork();
02736                 if (pid == 0)
02737                 { 
02738                         execv(cmd.c_str(), cmdargv);            
02739                         llwarns << "execv failure when trying to start " << cmd << llendl;
02740                         _exit(1); 
02741                 } else {
02742                         if (pid > 0)
02743                         {
02744                                 
02745                                 
02746                                 
02749                         } else {
02750                                 llwarns << "fork failure." << llendl;
02751                         }
02752                 }
02753         }
02754         
02755         
02756         exit(1);
02757 #else
02758     #error do something with your platform.
02759 #endif // LL_DARWIN
02760 
02761         return;
02762 }
02763 
02764 
02765 
02766 BOOL init_cache()
02767 {
02768         gPurgeCache = FALSE;
02769         
02770         if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
02771                 gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
02772         {
02773                 gSavedSettings.setBOOL("PurgeCacheOnNextStartup", FALSE);
02774                 gPurgeCache = TRUE;
02775         }
02776         
02777         else
02778         {
02779                 static const S32 cache_version = 5;
02780                 if (gSavedSettings.getS32("LocalCacheVersion") != cache_version)
02781                 {
02782                         gPurgeCache = TRUE;
02783                         gSavedSettings.setS32("LocalCacheVersion", cache_version);
02784                 }
02785         }
02786         
02787         
02788         LLString cache_location = gSavedSettings.getString("CacheLocation");
02789         LLString new_cache_location = gSavedSettings.getString("NewCacheLocation");
02790         if (new_cache_location != cache_location)
02791         {
02792                 gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
02793                 purge_cache(); 
02794                 gSavedSettings.setString("CacheLocation", new_cache_location);
02795         }
02796         
02797         if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
02798         {
02799                 llwarns << "Unable to set cache location" << llendl;
02800                 gSavedSettings.setString("CacheLocation", "");
02801         }
02802         
02803         if (gPurgeCache)
02804         {
02805                 LLSplashScreen::update("Clearing cache...");
02806                 purge_cache();
02807         }
02808 
02809         LLSplashScreen::update("Initializing Texture Cache...");
02810         
02811         
02812         
02813         BOOL read_only = gSecondInstance ? TRUE : FALSE;
02814         const S32 MB = 1024*1024;
02815         S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
02816         const S64 MAX_CACHE_SIZE = 1024*MB;
02817         cache_size = llmin(cache_size, MAX_CACHE_SIZE);
02818         S64 texture_cache_size = ((cache_size * 8)/10);
02819         S64 extra = gTextureCache->initCache(LL_PATH_CACHE, texture_cache_size, read_only);
02820         texture_cache_size -= extra;
02821 
02822         LLSplashScreen::update("Initializing VFS...");
02823         
02824         
02825         S64 vfs_size = cache_size - texture_cache_size;
02826         const S64 MAX_VFS_SIZE = 1024 * MB; 
02827         vfs_size = llmin(vfs_size, MAX_VFS_SIZE);
02828         vfs_size = (vfs_size / MB) * MB; 
02829         U32 vfs_size_u32 = (U32)vfs_size;
02830         U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
02831         bool resize_vfs = (vfs_size_u32 != old_vfs_size);
02832         if (resize_vfs)
02833         {
02834                 gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB);
02835         }
02836         llinfos << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << llendl;
02837         
02838         
02839         
02840         srand(time(NULL));              
02841         U32 old_salt = gSavedSettings.getU32("VFSSalt");
02842         U32 new_salt;
02843         char old_vfs_data_file[LL_MAX_PATH];            
02844         char old_vfs_index_file[LL_MAX_PATH];                   
02845         char new_vfs_data_file[LL_MAX_PATH];            
02846         char new_vfs_index_file[LL_MAX_PATH];   
02847         char static_vfs_index_file[LL_MAX_PATH];        
02848         char static_vfs_data_file[LL_MAX_PATH]; 
02849 
02850         if (gMultipleViewersOK)
02851         {
02852                 
02853                 new_salt = old_salt;
02854         }
02855         else
02856         {
02857                 do
02858                 {
02859                         new_salt = rand();
02860                 } while( new_salt == old_salt );
02861         }
02862 
02863         snprintf(old_vfs_data_file,  LL_MAX_PATH, "%s%u",               
02864                 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE).c_str(),
02865                 old_salt);
02866 
02867         
02868         llstat s;
02869         S32 stat_result = LLFile::stat(old_vfs_data_file, &s);
02870         if (stat_result)
02871         {
02872                 
02873                 std::string mask;
02874                 mask = gDirUtilp->getDirDelimiter();
02875                 mask += VFS_DATA_FILE_BASE;
02876                 mask += "*";
02877 
02878                 std::string dir;
02879                 dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
02880 
02881                 std::string found_file;
02882                 if (gDirUtilp->getNextFileInDir(dir, mask, found_file, FALSE))
02883                 {
02884                         snprintf(old_vfs_data_file, LL_MAX_PATH, "%s%s%s", dir.c_str(), gDirUtilp->getDirDelimiter().c_str(), found_file.c_str());              
02885 
02886                         S32 start_pos;
02887                         S32 length = strlen(found_file.c_str());                
02888                         for (start_pos = length - 1; start_pos >= 0; start_pos--)
02889                         {
02890                                 if (found_file[start_pos] == '.')
02891                                 {
02892                                         start_pos++;
02893                                         break;
02894                                 }
02895                         }
02896                         if (start_pos > 0)
02897                         {
02898                                 sscanf(found_file.c_str() + start_pos, "%d", &old_salt);
02899                         }
02900                         llinfos << "Default vfs data file not present, found " << old_vfs_data_file << llendl;
02901                         llinfos << "Old salt: " << old_salt << llendl;
02902                 }
02903         }
02904 
02905         snprintf(old_vfs_index_file, LL_MAX_PATH, "%s%u",               
02906                         gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE).c_str(),
02907                         old_salt);
02908 
02909         stat_result = LLFile::stat(old_vfs_index_file, &s);
02910         if (stat_result)
02911         {
02912                 
02913                 llwarns << "Bad or missing vfx index file " << old_vfs_index_file << llendl;
02914                 llwarns << "Removing old vfs data file " << old_vfs_data_file << llendl;
02915                 LLFile::remove(old_vfs_data_file);
02916                 LLFile::remove(old_vfs_index_file);
02917                 
02918                 
02919                 std::string dir;
02920                 dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
02921 
02922                 std::string mask;
02923                 mask = gDirUtilp->getDirDelimiter();
02924                 mask += VFS_DATA_FILE_BASE;
02925                 mask += "*";
02926 
02927                 gDirUtilp->deleteFilesInDir(dir, mask);
02928 
02929                 mask = gDirUtilp->getDirDelimiter();
02930                 mask += VFS_INDEX_FILE_BASE;
02931                 mask += "*";
02932 
02933                 gDirUtilp->deleteFilesInDir(dir, mask);
02934         }
02935 
02936         snprintf(new_vfs_data_file, LL_MAX_PATH, "%s%u",                
02937                 gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE).c_str(),
02938                 new_salt);
02939 
02940         snprintf(new_vfs_index_file, LL_MAX_PATH, "%s%u", gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE).c_str(),           
02941                 new_salt);
02942 
02943 
02944         strncpy(static_vfs_data_file, gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2").c_str(), LL_MAX_PATH -1);          
02945         static_vfs_data_file[LL_MAX_PATH -1] = '\0';
02946         strncpy(static_vfs_index_file, gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2").c_str(), LL_MAX_PATH -1);                
02947         static_vfs_index_file[LL_MAX_PATH -1] = '\0';
02948 
02949         if (resize_vfs)
02950         {
02951                 llinfos << "Removing old vfs and re-sizing" << llendl;
02952                 
02953                 LLFile::remove(old_vfs_data_file);
02954                 LLFile::remove(old_vfs_index_file);
02955         }
02956         else if (old_salt != new_salt)
02957         {
02958                 
02959                 llinfos << "Renaming " << old_vfs_data_file << " to " << new_vfs_data_file << llendl;
02960                 llinfos << "Renaming " << old_vfs_index_file << " to " << new_vfs_index_file << llendl;
02961                 LLFile::rename(old_vfs_data_file, new_vfs_data_file);
02962                 LLFile::rename(old_vfs_index_file, new_vfs_index_file);
02963         }
02964 
02965         
02966         gSavedSettings.setU32("VFSSalt", new_salt);
02967 
02968         
02969         gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, FALSE, vfs_size_u32, FALSE);
02970         if( VFSVALID_BAD_CORRUPT == gVFS->getValidState() )
02971         {
02972                 
02973                 
02974                 llwarns << "VFS corrupt, deleted.  Making new VFS." << llendl;
02975                 delete gVFS;
02976                 gVFS = new LLVFS(new_vfs_index_file, new_vfs_data_file, FALSE, vfs_size_u32, FALSE);
02977         }
02978 
02979         gStaticVFS = new LLVFS(static_vfs_index_file, static_vfs_data_file, TRUE, 0, FALSE);
02980 
02981         BOOL success = gVFS->isValid() && gStaticVFS->isValid();
02982         if( !success )
02983         {
02984                 return FALSE;
02985         }
02986         else
02987         {
02988                 LLVFile::initClass();
02989                 return TRUE;
02990         }
02991 }
02992 
02993 #if LL_DARWIN
02994 
02995 OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
02996 {
02997         OSErr result = noErr;
02998         DescType actualType;
02999         char buffer[1024];              
03000         Size size;
03001         
03002         result = AEGetParamPtr (
03003                 messagein,
03004                 keyDirectObject,
03005                 typeCString,
03006                 &actualType,
03007                 (Ptr)buffer,
03008                 sizeof(buffer),
03009                 &size); 
03010         
03011         if(result == noErr)
03012         {
03013                 std::string url = buffer;
03014                 LLURLDispatcher::dispatch(url);
03015         }
03016         
03017         return(result);
03018 }
03019 
03020 OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
03021 {
03022         OSErr result = noErr;
03023         
03024         app_user_quit();
03025         
03026         return(result);
03027 }
03028 
03029 OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
03030 {
03031         OSStatus result = eventNotHandledErr;
03032         OSStatus err;
03033         UInt32 evtClass = GetEventClass(event);
03034         UInt32 evtKind = GetEventKind(event);
03035         WindowRef window = (WindowRef)userdata;
03036         
03037         if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
03038         {
03039                 HICommand cmd;
03040                 err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
03041                 
03042                 if(err == noErr)
03043                 {
03044                         switch(cmd.commandID)
03045                         {
03046                                 case kHICommandOK:
03047                                         QuitAppModalLoopForWindow(window);
03048                                         result = noErr;
03049                                 break;
03050                                 
03051                                 case kHICommandCancel:
03052                                         QuitAppModalLoopForWindow(window);
03053                                         result = userCanceledErr;
03054                                 break;
03055                         }
03056                 }
03057         }
03058         
03059         return(result);
03060 }
03061 
03062 OSStatus DisplayReleaseNotes(void)
03063 {
03064         OSStatus err;
03065         IBNibRef nib = NULL;
03066         WindowRef window = NULL;
03067         
03068         err = CreateNibReference(CFSTR("SecondLife"), &nib);
03069         
03070         if(err == noErr)
03071         {
03072                 CreateWindowFromNib(nib, CFSTR("Release Notes"), &window);
03073         }
03074                 
03075         if(err == noErr)
03076         {
03077                 
03078                 HIViewRef textView;
03079                 ControlID id;
03080 
03081                 id.signature = 'text';
03082                 id.id = 0;
03083 
03084                 std::string releaseNotesText;
03085                 _read_file_into_string(releaseNotesText, "releasenotes.txt");
03086 
03087                 err = HIViewFindByID(HIViewGetRoot(window), id, &textView);
03088                 
03089                 if(err == noErr)
03090                 {
03091                         
03092                         CFStringRef str = CFStringCreateWithBytes(
03093                                 NULL, 
03094                                 (const UInt8*)releaseNotesText.c_str(), 
03095                                 releaseNotesText.size(), 
03096                                 kCFStringEncodingWindowsLatin1,                 
03097                                 FALSE);
03098                         
03099                         if(str != NULL)
03100                         {
03101                                 int size = CFStringGetLength(str);
03102 
03103                                 if(size > 0)
03104                                 {
03105                                         UniChar *chars = new UniChar[size + 1];
03106                                         CFStringGetCharacters(str, CFRangeMake(0, size), chars);
03107                                 
03108                                         err = TXNSetData(HITextViewGetTXNObject(textView), kTXNUnicodeTextData, chars, size * sizeof(UniChar), kTXNStartOffset, kTXNStartOffset);
03109                                         
03110                                         delete[] chars;
03111                                 }
03112                                 
03113                                 CFRelease(str);
03114                         }
03115                         else
03116                         {
03117                                 
03118                                 err = TXNSetData(HITextViewGetTXNObject(textView), kTXNTextData, releaseNotesText.c_str(), releaseNotesText.size(), kTXNStartOffset, kTXNStartOffset);
03119                         }
03120                 }
03121                 
03122                 
03123                 if(err == noErr)
03124                 {
03125                         err = TXNSetSelection(HITextViewGetTXNObject(textView), kTXNStartOffset, kTXNStartOffset);
03126                 }
03127                 
03128                 if(err == noErr)
03129                 {
03130                         
03131                         TXNShowSelection(HITextViewGetTXNObject(textView), false);
03132                 }
03133         }
03134 
03135         if(err == noErr)
03136         {
03137                 ShowWindow(window);
03138         }
03139 
03140         if(err == noErr)
03141         {
03142                 
03143                 EventHandlerRef handler = NULL;
03144                 EventTypeSpec handlerEvents[] = 
03145                 {
03146                         { kEventClassCommand, kEventCommandProcess }
03147                 };
03148 
03149                 InstallWindowEventHandler(
03150                                 window, 
03151                                 NewEventHandlerUPP(simpleDialogHandler), 
03152                                 GetEventTypeCount (handlerEvents), 
03153                                 handlerEvents, 
03154                                 (void*)window, 
03155                                 &handler);
03156         }
03157                         
03158         if(err == noErr)
03159         {
03160                 RunAppModalLoopForWindow(window);
03161         }
03162                         
03163         if(window != NULL)
03164         {
03165                 DisposeWindow(window);
03166         }
03167         
03168         if(nib != NULL)
03169         {
03170                 DisposeNibReference(nib);
03171         }
03172 
03173         return(err);
03174 }
03175 
03176 void init_apple_menu(const char* product)
03177 {
03178         
03179         {
03180                 OSStatus err;
03181                 IBNibRef nib = NULL;
03182                 
03183                 err = CreateNibReference(CFSTR("SecondLife"), &nib);
03184                 
03185                 if(err == noErr)
03186                 {
03187                         
03188                         SetMenuBarFromNib(nib, CFSTR("MenuBar"));
03189                 }
03190 
03191                 if(nib != NULL)
03192                 {
03193                         DisposeNibReference(nib);
03194                 }
03195         }
03196         
03197         
03198         
03199         if(AEInstallEventHandler('GURL', 'GURL', NewAEEventHandlerUPP(AEGURLHandler),0, false) != noErr)
03200         {
03201                 
03202                 llinfos << "Couldn't install 'GURL' AppleEvent handler.  Continuing..." << llendl;
03203         }
03204 
03205         
03206         if(AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(AEQuitHandler),0, false) != noErr)
03207         {
03208                 
03209                 llinfos << "Couldn't install Quit AppleEvent handler.  Continuing..." << llendl;
03210         }
03211 }
03212 #endif
03213 
03214 void user_logout()
03215 {
03216         if (!gDoneLogout)
03217         {
03218                 LLMessageSystem* msg = gMessageSystem;
03219                 if (msg)
03220                 {
03221                                 gSavedSettings.setBOOL("LoggedIn", FALSE);
03222                 }
03223                 gDoneLogout = TRUE;
03224         }
03225 }
03226 
03227 
03228 
03229 
03230 
03231 void save_final_snapshot(void*)
03232 {
03233         if (!gHaveSavedSnapshot && !gNoRender)
03234         {
03235                 gSavedSettings.setVector3d("FocusPosOnLogout", gAgent.calcFocusPositionTargetGlobal());
03236                 gSavedSettings.setVector3d("CameraPosOnLogout", gAgent.calcCameraPositionTargetGlobal());
03237                 gViewerWindow->setCursor(UI_CURSOR_WAIT);
03238                 gAgent.changeCameraToThirdPerson( FALSE );      
03239                 gSavedSettings.setBOOL("ShowParcelOwners", FALSE);
03240                 idle();
03241 
03242                 LLString snap_filename = gDirUtilp->getLindenUserDir();
03243                 snap_filename += gDirUtilp->getDirDelimiter();
03244                 snap_filename += SCREEN_LAST_FILENAME;
03245                 gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidth(), gViewerWindow->getWindowHeight(), FALSE, TRUE);
03246                 gHaveSavedSnapshot = TRUE;
03247         }
03248 }
03249 
03250 
03251 
03252 void app_force_quit(const char* launch_file_on_quit)
03253 {
03254         
03255         
03256         
03257         if (launch_file_on_quit)
03258         {
03259                 gLaunchFileOnQuit.assign( (const char*)launch_file_on_quit );
03260         }
03261 
03262         gQuit = TRUE;
03263 }
03264 
03265 static void finish_quit(S32 option, void *userdata)
03266 {
03267         if (option == 0)
03268         {
03269                 app_request_quit();
03270         }
03271 }
03272 
03273 void app_user_quit()
03274 {
03275         gViewerWindow->alertXml("ConfirmQuit", finish_quit, NULL);
03276 }
03277 
03278   
03279 
03280 
03281 void app_request_quit()
03282 {
03283         llinfos << "app_request_quit" << llendl;
03284 
03285         LLViewerRegion* region = gAgent.getRegion();
03286         
03287         if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
03288         {
03289                 
03290                 app_force_quit(NULL);
03291                 return;
03292         }
03293 
03294         if (gHUDManager)
03295         {
03296                 LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
03297                 effectp->setPositionGlobal(gAgent.getPositionGlobal());
03298                 effectp->setColor(LLColor4U(gAgent.getEffectColor()));
03299                 gHUDManager->sendEffects();
03300         }
03301 
03302         
03303         
03304         if (gFloaterView)
03305         {
03306                 
03307                 gFloaterView->closeAllChildren(true);
03308         }
03309 
03310         send_stats();
03311 
03312         gLogoutTimer.reset();
03313         gQuitRequested = TRUE;
03314 }
03315 
03316 
03317 
03318 
03319 void app_abort_quit()
03320 {
03321         llinfos << "app_abort_quit()" << llendl;
03322         gQuitRequested = FALSE;
03323 }
03324 
03325 void idle_shutdown()
03326 {
03327         
03328         if (LLModalDialog::activeCount() > 0)
03329         {
03330                 return;
03331         }
03332 
03333         
03334         if(gIMMgr)
03335         {
03336                 gIMMgr->disconnectAllSessions();
03337         }
03338         
03339         
03340         if (gFloaterView
03341                 && !gFloaterView->allChildrenClosed())
03342         {
03343                 return;
03344         }
03345 
03346         static bool saved_snapshot = false;
03347         if (!saved_snapshot)
03348         {
03349                 saved_snapshot = true;
03350                 save_final_snapshot(NULL);
03351                 return;
03352         }
03353 
03354         const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
03355 
03356         S32 pending_uploads = gAssetStorage->getNumPendingUploads();
03357         if (pending_uploads > 0
03358                 && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
03359                 && !gLogoutRequestSent)
03360         {
03361                 static S32 total_uploads = 0;
03362                 
03363                 total_uploads = llmax(total_uploads, pending_uploads);
03364                 gViewerWindow->setShowProgress(TRUE);
03365                 S32 finished_uploads = total_uploads - pending_uploads;
03366                 F32 percent = 100.f * finished_uploads / total_uploads;
03367                 gViewerWindow->setProgressPercent(percent);
03368                 char buffer[MAX_STRING];                
03369                 snprintf(buffer, MAX_STRING, "Saving final data...");           
03370                 gViewerWindow->setProgressString(buffer);
03371                 return;
03372         }
03373 
03374         
03375         if( !gLogoutRequestSent )
03376         {
03377                 send_logout_request();
03378 
03379                 
03380                 gViewerWindow->setShowProgress(TRUE);
03381                 gViewerWindow->setProgressPercent(100.f);
03382                 gViewerWindow->setProgressString("Logging out...");
03383                 return;
03384         }
03385 
03386         
03387         if( gLogoutRequestSent 
03388                 && gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime )
03389         {
03390                 app_force_quit(NULL);
03391                 return;
03392         }
03393 }
03394 
03395 
03396 U32             gTotalLandIn = 0, gTotalLandOut = 0;
03397 U32             gTotalWaterIn = 0, gTotalWaterOut = 0;
03398 
03399 F32             gAveLandCompression = 0.f, gAveWaterCompression = 0.f;
03400 F32             gBestLandCompression = 1.f, gBestWaterCompression = 1.f;
03401 F32             gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f;
03402 
03403 F32             gFPSClamped = 10.f;                                             
03404 F32             gFrameDTClamped = 0.f;                                  
03405 F32             gFrameDT = 0.f;
03406 
03407 
03408 U32             gPacketsIn = 0;
03409 
03410 U32             gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0;
03411 U32             gObjectBits = 0;
03412 F32             gAvgSimPing = 0.f;
03413 
03414 
03415 extern U32  gVisCompared;
03416 extern U32  gVisTested;
03417 
03418 
03419 void update_statistics(U32 frame_count)
03420 {
03421         gTotalWorldBytes += gVLManager.getTotalBytes();
03422         gTotalObjectBytes += gObjectBits / 8;
03423         gTotalTextureBytes += LLViewerImageList::sTextureBits / 8;
03424 
03425         
03426         if (gFrameIntervalSeconds > 0.f)
03427         {
03428                 if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
03429                 {
03430                         gViewerStats->incStat(LLViewerStats::ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds);
03431                 }
03432                 else if (gAgent.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
03433                 {
03434                         gViewerStats->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds);
03435                 }
03436                 else if (gFloaterTools && gFloaterTools->getVisible())
03437                 {
03438                         gViewerStats->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds);
03439                 }
03440         }
03441         gViewerStats->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable"));
03442         gViewerStats->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gSavedSettings.getS32("RenderLightingDetail"));
03443         gViewerStats->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip"));
03444         gViewerStats->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles"));
03445 #if 0 // 1.9.2
03446         gViewerStats->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject"));
03447         gViewerStats->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar"));
03448         gViewerStats->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment"));
03449 #endif
03450         gViewerStats->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_FRAME));
03451         F64 idle_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IDLE);
03452         F64 network_secs = gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_NETWORK);
03453         gViewerStats->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs);
03454         gViewerStats->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs);
03455         gViewerStats->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_IMAGE_UPDATE));
03456         gViewerStats->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_REBUILD));
03457         gViewerStats->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime(LLFastTimer::FTM_RENDER_GEOMETRY));
03458                 
03459         LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
03460         if (cdp)
03461         {
03462                 gViewerStats->mSimPingStat.addValue(cdp->getPingDelay());
03463                 gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1);
03464                 gSimPingCount++;
03465         }
03466         else
03467         {
03468                 gViewerStats->mSimPingStat.addValue(10000);
03469         }
03470 
03471         if (gFocusMgr.getAppHasFocus())
03472         {
03473                 gViewerStats->mFPSStat.addValue(1);
03474         }
03475         F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
03476         gViewerStats->mLayersKBitStat.addValue(layer_bits/1024.f);
03477         gViewerStats->mObjectKBitStat.addValue(gObjectBits/1024.f);
03478         gViewerStats->mTextureKBitStat.addValue(LLViewerImageList::sTextureBits/1024.f);
03479         gViewerStats->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
03480         gViewerStats->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
03481         gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
03482 
03483         static S32 tex_bits_idle_count = 0;
03484         if (LLViewerImageList::sTextureBits == 0)
03485         {
03486                 if (++tex_bits_idle_count >= 30)
03487                         gDebugTimers[0].pause();
03488         }
03489         else
03490         {
03491                 tex_bits_idle_count = 0;
03492                 gDebugTimers[0].unpause();
03493         }
03494         
03495         gViewerStats->mTexturePacketsStat.addValue(LLViewerImageList::sTexturePackets);
03496 
03497         gViewerStats->mUserserverPingStat.addValue(0); 
03498 
03499         
03500         #if LL_LIBXUL_ENABLED
03501         {
03502                 BOOL result = gViewerHtmlHelp.getFloaterOpened();
03503                 gViewerStats->setStat(LLViewerStats::ST_LIBXUL_WIDGET_USED, (F64)result);
03504         }
03505         #endif
03506 
03507         {
03508                 static F32 visible_avatar_frames = 0.f;
03509                 static F32 avg_visible_avatars = 0;
03510                 F32 visible_avatars = (F32)LLVOAvatar::sNumVisibleAvatars;
03511                 if (visible_avatars > 0.f)
03512                 {
03513                         visible_avatar_frames = 1.f;
03514                         avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames;
03515                 }
03516                 gViewerStats->setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars);
03517         }
03518         gWorldp->updateNetStats();
03519         gWorldp->requestCacheMisses();
03520         
03521         
03522         gVLManager.resetBitCounts();
03523         gObjectBits = 0;
03524 
03525 
03526         LLViewerImageList::sTextureBits = 0;
03527         LLViewerImageList::sTexturePackets = 0;
03528 
03529 #if LL_WINDOWS && LL_LCD_COMPILE
03530         bool LCDenabled = gLcdScreen->Enabled();
03531         gViewerStats->setStat(LLViewerStats::ST_LOGITECH_LCD, LCDenabled);
03532 #else
03533         gViewerStats->setStat(LLViewerStats::ST_LOGITECH_LCD, false);
03534 #endif
03535 
03536 }
03537 
03538 
03539 
03540 
03541 
03542 #define TIME_THROTTLE_MESSAGES
03543 
03544 #ifdef TIME_THROTTLE_MESSAGES
03545 #define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
03546 static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
03547 #endif
03548 
03549 void idle_network()
03550 {
03551         gObjectList.mNumNewObjects = 0;
03552         S32 total_decoded = 0;
03553 
03554         if (!gSavedSettings.getBOOL("SpeedTest"))
03555         {
03556                 LLFastTimer t(LLFastTimer::FTM_IDLE_NETWORK); 
03557                 
03558                 
03559                 gCacheName->processPending();
03560 
03561                 LLTimer check_message_timer;
03562                 
03563                 stop_glerror();
03564                 const S64 frame_count = gFrameCount;  
03565                 F32 total_time = 0.0f;
03566                 while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) 
03567                 {
03568                         if (gDoDisconnect)
03569                         {
03570                                 
03571                                 
03572                                 
03573                                 break;
03574                         }
03575                         stop_glerror();
03576 
03577                         total_decoded++;
03578                         gPacketsIn++;
03579 
03580                         if (total_decoded > MESSAGE_MAX_PER_FRAME)
03581                         {
03582                                 break;
03583                         }
03584 
03585 #ifdef TIME_THROTTLE_MESSAGES
03586                         
03587                         
03588                         
03589                         
03590                         total_time = check_message_timer.getElapsedTimeF32();
03591                         if (total_time >= CheckMessagesMaxTime)
03592                                 break;
03593 #endif
03594                 }
03595                 
03596                 gMessageSystem->processAcks();
03597 
03598 #ifdef TIME_THROTTLE_MESSAGES
03599                 if (total_time >= CheckMessagesMaxTime)
03600                 {
03601                         
03602                         CheckMessagesMaxTime *= 1.035f; 
03603                 }
03604                 else
03605                 {
03606                         
03607                         CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
03608                 }
03609 #endif
03610                 
03611 
03612 
03613                 
03614                 gAgent.resetControlFlags();
03615                 stop_glerror();
03616 
03617                 
03618                 
03619                 S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
03620 
03621                 if( remaining_possible_decodes <= 0 )
03622                 {
03623                         llinfos << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << llendl;
03624                 }
03625 
03626                 if (gPrintMessagesThisFrame)
03627                 {
03628                         llinfos << "Decoded " << total_decoded << " msgs this frame!" << llendl;
03629                         gPrintMessagesThisFrame = FALSE;
03630                 }
03631         }
03632 
03633         gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
03634 
03635         
03636         gXferManager->retransmitUnackedPackets();
03637         gAssetStorage->checkForTimeouts();
03638 
03639         gViewerThrottle.updateDynamicThrottle();
03640 }
03641 
03642 void idle_afk_check()
03643 {
03644         
03645         if (gAllowIdleAFK && (gAwayTriggerTimer.getElapsedTimeF32() > gAFKTimeout))
03646         {
03647                 gAgent.setAFK();
03648         }
03649 }
03650 void request_initial_instant_messages()
03651 {
03652         static BOOL requested = FALSE;
03653         if (!requested
03654                 && gMuteListp
03655                 && gMuteListp->isLoaded()
03656                 && gAgent.getAvatarObject())
03657         {
03658                 
03659                 
03660                 
03661                 LLMessageSystem* msg = gMessageSystem;
03662                 msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
03663                 msg->nextBlockFast(_PREHASH_AgentData);
03664                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
03665                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03666                 gAgent.sendReliableMessage();
03667                 requested = TRUE;
03668         }
03669 }
03670 
03672 
03673 
03674 
03675 
03677 
03678 void idle()
03679 {
03680         
03681         static LLTimer idle_timer;
03682 
03683         LLControlBase::updateAllListeners();
03684 
03685         LLFrameTimer::updateFrameTime();
03686         LLEventTimer::updateClass();
03687         LLCriticalDamp::updateInterpolants();
03688         LLMortician::updateClass();
03689         F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
03690 
03691         
03692         
03693         
03694         const F32 MIN_FRAME_RATE = 1.f;
03695         const F32 MAX_FRAME_RATE = 200.f;
03696 
03697         F32 frame_rate_clamped = 1.f / dt_raw;
03698         frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE);
03699         gFrameDTClamped = 1.f / frame_rate_clamped;
03700 
03701         
03702         
03703         gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f;
03704 
03705         if (gQuitAfterSeconds > 0.f)
03706         {
03707                 if (gRenderStartTime.getElapsedTimeF32() > gQuitAfterSeconds)
03708                 {
03709                         app_force_quit(NULL);
03710                 }
03711         }
03712 
03713         
03714         
03715         request_initial_instant_messages();
03716 
03718         
03719         
03720         
03721 
03722         if (LLStartUp::getStartupState() < STATE_STARTED)
03723         {
03724                 
03725                 if (!idle_startup())
03726                 {
03727                         return;
03728                 }
03729         }
03730 
03731         
03732     F32 yaw = 0.f;                              
03733 
03734         if (!gDisconnected)
03735         {
03736                 LLFastTimer t(LLFastTimer::FTM_NETWORK);
03737                 
03738             
03739             gWorldp->setSpaceTimeUSec(gWorldp->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC));
03740     
03741     
03743             
03744             
03745             
03746 
03747                 if (gRotateRight)
03748                 {
03749                         gAgent.moveYaw(-1.f);
03750                 }
03751 
03752             
03753             gAgentPilot.updateTarget();
03754             gAgent.autoPilot(&yaw);
03755     
03756             static LLFrameTimer agent_update_timer;
03757             static U32                          last_control_flags;
03758     
03759             
03760             F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
03761             BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags());
03762     
03763             if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
03764             {
03765                     
03766                     last_control_flags = gAgent.getControlFlags();
03767                     send_agent_update(TRUE);
03768                     agent_update_timer.reset();
03769             }
03770         }
03771 
03773         
03774         
03775         
03776         
03777 
03778         {
03779                 static LLFrameTimer     viewer_stats_timer;
03780                 reset_statistics();
03781 
03782                 
03783                 
03784 
03785                 if (viewer_stats_timer.getElapsedTimeF32() >= 300.f && !gDisconnected)
03786                 {
03787                         llinfos << "Transmitting sessions stats" << llendl;
03788                         send_stats();
03789                         viewer_stats_timer.reset();
03790                 }
03791 
03792                 
03793                 static LLFrameTimer object_debug_timer;
03794                 if (object_debug_timer.getElapsedTimeF32() > 5.f)
03795                 {
03796                         object_debug_timer.reset();
03797                         if (gObjectList.mNumDeadObjectUpdates)
03798                         {
03799                                 llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
03800                                 gObjectList.mNumDeadObjectUpdates = 0;
03801                         }
03802                         if (gObjectList.mNumUnknownKills)
03803                         {
03804                                 llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
03805                                 gObjectList.mNumUnknownKills = 0;
03806                         }
03807                         if (gObjectList.mNumUnknownUpdates)
03808                         {
03809                                 llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
03810                                 gObjectList.mNumUnknownUpdates = 0;
03811                         }
03812                 }
03813                 gFrameStats.addFrameData();
03814         }
03815 
03816         
03817         gFloaterAvatarList->updateAvatarList();
03818 
03819         gFloaterEventLog->updateWindow();
03820 
03821         if (!gDisconnected)
03822         {
03823                 LLFastTimer t(LLFastTimer::FTM_NETWORK);
03824         
03826             
03827             
03828             
03829             
03830             
03831             
03832     
03833             gFrameStats.start(LLFrameStats::IDLE_NETWORK);
03834                 idle_network();
03835             stop_glerror();
03836                 
03837             gFrameStats.start(LLFrameStats::AGENT_MISC);
03838 
03839                 
03840                 idle_afk_check();
03841 
03842                 
03843                 update_statistics(gFrameCount);
03844 
03845                 gViewerWindow->updateDebugText();
03846         }
03847 
03849         
03850         
03851         
03852         
03853 
03854         {
03855 
03856 
03857                 
03858                 gEventNotifier.update();
03859                 
03860                 gIdleCallbacks.callFunctions();
03861         }
03862         
03863         if (gDisconnected)
03864     {
03865                 return;
03866     }
03867 
03868         gViewerWindow->handlePerFrameHover();
03869 
03871         
03872         
03873                 LLCoordGL current_mouse = gViewerWindow->getCurrentMouse();
03874 
03875 
03876 
03877         {
03878                 
03879                 
03880                 
03881                 
03882                 gSelectMgr->deselectAllIfTooFar();
03883                 gSelectMgr->update(); 
03884         }
03885 
03886         {
03887                 LLFastTimer t(LLFastTimer::FTM_RESET_DRAWORDER);
03888                         
03890                 
03891                 
03892                 
03893                 
03894                 
03895                 
03896 
03897                 gPipeline.resetDrawOrders();
03898         }
03899         {
03900                 
03901                 gGestureManager.update();
03902 
03903                 gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
03904         }
03905 
03906         {
03907                 LLFastTimer t(LLFastTimer::FTM_OBJECTLIST_UPDATE); 
03908                 gFrameStats.start(LLFrameStats::OBJECT_UPDATE);
03909                 
03910                 if (!(gLogoutRequestSent && gHaveSavedSnapshot))
03911                 {
03912                         gObjectList.update(gAgent, *gWorldp);
03913                 }
03914         }
03915         
03916         {
03917                 LLFastTimer t(LLFastTimer::FTM_UPDATE_SKY);     
03918                 gSky.updateSky();
03919         }
03920 
03922         
03923         
03924         
03925         
03926 
03927         {
03928                 LLFastTimer t(LLFastTimer::FTM_CLEANUP);
03929                 gFrameStats.start(LLFrameStats::CLEAN_DEAD);
03930                 gObjectList.cleanDeadObjects();
03931                 LLDrawable::cleanupDeadDrawables();
03932         }
03933         
03934         
03935         
03936         
03937         
03938 
03940         
03941         
03942         
03943         
03944         
03945         
03946 
03947         {
03948                 
03949                 
03950                 gFrameStats.start(LLFrameStats::UPDATE_EFFECTS);
03951                 gSelectMgr->updateEffects();
03952                 gHUDManager->cleanupEffects();
03953                 gHUDManager->sendEffects();
03954         }
03955 
03956         stop_glerror();
03957 
03959         
03960         
03961         
03962 
03963         {
03964                 LLFastTimer t(LLFastTimer::FTM_NETWORK);
03965                 gVLManager.unpackData();
03966         }
03967         
03969         
03970         
03971         
03972 
03973         gWorldp->updateVisibilities();
03974         {
03975                 const F32 max_region_update_time = .001f; 
03976                 LLFastTimer t(LLFastTimer::FTM_REGION_UPDATE);
03977                 gWorldp->updateRegions(max_region_update_time);
03978         }
03979         
03981         
03982         
03983         
03984 
03985         if (!gNoRender)
03986         {
03987                 gWorldp->updateClouds(gFrameDTClamped);
03988                 gSky.propagateHeavenlyBodies(gFrameDTClamped);                          
03989 
03990                 
03991                 LLVector3 wind_position_region;
03992                 static LLVector3 average_wind;
03993 
03994                 LLViewerRegion *regionp;
03995                 regionp = gWorldp->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal());       
03996                 if (regionp)
03997                 {
03998                         gWindVec = regionp->mWind.getVelocity(wind_position_region);
03999 
04000                         
04001                         
04002                         average_wind = regionp->mWind.getAverage();
04003                         F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
04004                         
04005                         gSky.setCloudDensityAtAgent(cloud_density);
04006                         gSky.setWind(average_wind);
04007                         
04008                 }
04009                 else
04010                 {
04011                         gWindVec.setVec(0.0f, 0.0f, 0.0f);
04012                 }
04013         }
04014         stop_glerror();
04015         
04017         
04018         
04019         
04020         
04021         
04022         gFrameStats.start(LLFrameStats::IMAGE_UPDATE);
04023 
04024         LLFastTimer t(LLFastTimer::FTM_IMAGE_UPDATE);
04025         
04026         LLViewerImage::updateClass(gCamera->getVelocityStat()->getMean(),
04027                                                                 gCamera->getAngularVelocityStat()->getMean());
04028 
04029         gBumpImageList.updateImages();  
04030 
04031         const F32 max_image_decode_time = 0.005f; 
04032         gImageList.updateImages(max_image_decode_time);
04033         stop_glerror();
04034 
04036         
04037         
04038         
04039         
04040         
04041         if (!gNoRender)
04042         {
04043                 gFrameStats.start(LLFrameStats::UPDATE_MOVE);
04044                 gPipeline.updateMove();
04045 
04046                 gFrameStats.start(LLFrameStats::UPDATE_PARTICLES);
04047                 gWorldp->updateParticles();
04048         }
04049         stop_glerror();
04050 
04051         if (!LLViewerJoystick::sOverrideCamera)
04052         {
04053                 gAgent.updateCamera();
04054         }
04055         else
04056         {
04057                 LLViewerJoystick::updateCamera();
04058         }
04059 
04060         
04061         {
04062                 LLFastTimer t(LLFastTimer::FTM_LOD_UPDATE);
04063                 gObjectList.updateApparentAngles(gAgent);
04064         }
04065 
04066         {
04067                 gFrameStats.start(LLFrameStats::AUDIO);
04068                 LLFastTimer t(LLFastTimer::FTM_AUDIO_UPDATE);
04069                 
04070                 if (gAudiop)
04071                 {
04072                         audio_update_volume(false);
04073                         audio_update_listener();
04074                         audio_update_wind(false);
04075 
04076                         
04077                         const F32 max_audio_decode_time = 0.002f; 
04078                         gAudiop->idle(max_audio_decode_time);
04079                 }
04080         }
04081         
04082         if ( gTrustNet )
04083         {
04084                 gTrustNet->processRequests();
04085         }
04086 
04087         
04088         
04089         
04090         if (gQuitRequested)
04091         {
04092                 idle_shutdown();
04093         }
04094 
04095         stop_glerror();
04096 }
04097 
04098 
04099 F32 mouse_x_from_center(S32 x)
04100 {
04101         return ((F32) x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f;
04102 }
04103 
04104 
04105 F32 mouse_y_from_center(S32 y)
04106 {
04107         return ((F32) y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f;
04108 }
04109 
04110 
04112 
04113 void init_audio() 
04114 {
04115         if (!gAudiop) 
04116         {
04117                 llwarns << "Failed to create an appropriate Audio Engine" << llendl;
04118                 return;
04119         }
04120         LLVector3d lpos_global = gAgent.getCameraPositionGlobal();
04121         LLVector3 lpos_global_f;
04122 
04123         lpos_global_f.setVec(lpos_global);
04124                                         
04125         gAudiop->setListener(lpos_global_f,
04126                                                   LLVector3::zero,      
04127                                                   gCamera->getUpAxis(),
04128                                                   gCamera->getAtAxis());
04129 
04130 
04131 
04132         BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio");
04133 
04134         if (!mute_audio && gPreloadSounds)
04135         {
04136                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndAlert")));
04137                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndBadKeystroke")));
04138                 
04139                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndClick")));
04140                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndClickRelease")));
04141                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndHealthReductionF")));
04142                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndHealthReductionM")));
04143                 
04144                 
04145                 
04146                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndInvalidOp")));
04147                 
04148                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndMoneyChangeDown")));
04149                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndMoneyChangeUp")));
04150                 
04151                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectCreate")));
04152                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectDelete")));
04153                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezIn")));
04154                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndObjectRezOut")));
04155                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuAppear")));
04156                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuHide")));
04157                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight0")));
04158                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight1")));
04159                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight2")));
04160                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight3")));
04161                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight4")));
04162                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight5")));
04163                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight6")));
04164                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndPieMenuSliceHighlight7")));
04165                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndSnapshot")));
04166                 
04167                 
04168                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndStartIM")));
04169                 
04170                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTeleportOut")));
04171                 
04172                 
04173                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndTyping")));
04174                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowClose")));
04175                 gAudiop->preloadSound(LLUUID(gSavedSettings.getString("UISndWindowOpen")));
04176         }
04177 
04178         audio_update_volume(true);
04179 }
04180 
04181 void audio_update_volume(bool force_update)
04182 {
04183         F32 master_volume = gSavedSettings.getF32("AudioLevelMaster");
04184         BOOL mute_audio = gSavedSettings.getBOOL("MuteAudio");
04185         if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
04186         {
04187                 mute_audio = TRUE;
04188         }
04189         F32 mute_volume = mute_audio ? 0.0f : 1.0f;
04190 
04191         
04192         if (gAudiop) 
04193         {
04194                 gAudiop->setMasterGain ( master_volume );
04195 
04196                 gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler"));
04197                 gAudiop->setDistanceFactor(gSavedSettings.getF32("AudioLevelDistance")); 
04198                 gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
04199 #ifdef kAUDIO_ENABLE_WIND
04200                 gAudiop->enableWind(!mute_audio);
04201 #endif
04202 
04203                 gAudiop->setMuted(mute_audio);
04204                 
04205                 if (force_update)
04206                 {
04207                         audio_update_wind(true);
04208                 }
04209         }
04210 
04211         
04212         if (gAudiop) 
04213         {               
04214                 F32 music_volume = gSavedSettings.getF32("AudioLevelMusic");
04215                 music_volume = mute_volume * master_volume * (music_volume*music_volume);
04216                 gAudiop->setInternetStreamGain ( music_volume );
04217         }
04218 
04219         
04220         if(LLMediaEngine::getInstance())
04221         {
04222                 F32 media_volume = gSavedSettings.getF32("AudioLevelMedia");
04223                 media_volume = mute_volume * master_volume * (media_volume*media_volume);
04224                 LLMediaEngine::getInstance()->setVolume(media_volume);
04225         }
04226 
04227         
04228         if (gVoiceClient)
04229         {
04230                 F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice");
04231                 voice_volume = mute_volume * master_volume * voice_volume;
04232                 gVoiceClient->setVoiceVolume(voice_volume);
04233                 gVoiceClient->setMicGain(gSavedSettings.getF32("AudioLevelMic"));
04234 
04235                 if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized")))
04236                 {
04237                         gVoiceClient->setMuteMic(true);
04238                 }
04239                 else
04240                 {
04241                         gVoiceClient->setMuteMic(false);
04242                 }
04243         }
04244 }
04245 
04246 void audio_update_listener()
04247 {
04248         if (gAudiop)
04249         {
04250                 
04251                 LLVector3d lpos_global = gAgent.getCameraPositionGlobal();              
04252                 LLVector3 lpos_global_f;
04253                 lpos_global_f.setVec(lpos_global);
04254         
04255                 gAudiop->setListener(lpos_global_f,
04256                                                          
04257                                                          
04258                                                          gAgent.getVelocity(),    
04259                                                          gCamera->getUpAxis(),
04260                                                          gCamera->getAtAxis());
04261         }
04262 }
04263 
04264 void audio_update_wind(bool force_update)
04265 {
04266 #ifdef kAUDIO_ENABLE_WIND
04267         
04268         
04269         
04270         LLViewerRegion* region = gAgent.getRegion();
04271         if (region)
04272         {
04273                 static F32 last_camera_water_height = -1000.f;
04274                 LLVector3 camera_pos = gAgent.getCameraPositionAgent();
04275                 F32 camera_water_height = camera_pos.mV[VZ] - region->getWaterHeight();
04276                 
04277                 
04278                 
04279                 
04280                 if (force_update || (last_camera_water_height * camera_water_height) < 0.f)
04281                 {
04282                         if (camera_water_height < 0.f)
04283                         {
04284                                 gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff") * LL_ROLLOFF_MULTIPLIER_UNDER_WATER);
04285                         }
04286                         else 
04287                         {
04288                                 gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff"));
04289                         }
04290                 }
04291                 
04292                 
04293                 
04294                 gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal(gWindVec - gAgent.getVelocity());
04295 
04296                 
04297                 
04298                 
04299                 gAudiop->mMaxWindGain = gSavedSettings.getF32("AudioLevelAmbient");
04300                 
04301                 last_camera_water_height = camera_water_height;
04302                 gAudiop->updateWind(gRelativeWindVec, camera_water_height);
04303         }
04304 #endif
04305 }
04306 
04307 
04309 
04310 BOOL raycast_for_new_obj_pos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face, 
04311                                                          BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region )
04312 {
04313         F32 max_dist_from_camera = gSavedSettings.getF32( "MaxSelectDistance" ) - 1.f;
04314 
04315         
04316         
04317         gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, NULL, FALSE);
04318         
04319         
04320         
04321         *hit_obj = gObjectList.findObject( gLastHitNonFloraObjectID );
04322         *hit_face = gLastHitNonFloraObjectFace;
04323         *b_hit_land = !(*hit_obj) && !gLastHitNonFloraPosGlobal.isExactlyZero();
04324         LLVector3d land_pos_global = gLastHitNonFloraPosGlobal;
04325 
04326         
04327         BOOL bypass_sim_raycast = FALSE;
04328         LLVector3d      surface_pos_global;
04329         if (*b_hit_land)
04330         {
04331                 surface_pos_global = land_pos_global; 
04332                 bypass_sim_raycast = TRUE;
04333         }
04334         else 
04335         if (*hit_obj)
04336         {
04337                 surface_pos_global = (*hit_obj)->getPositionGlobal();
04338         }
04339         else
04340         {
04341                 return FALSE;
04342         }
04343 
04344         
04345         LLVector3d ray_start_global = gAgent.getCameraPositionGlobal();
04346         F32 dist_to_surface_sq = (F32)((surface_pos_global - ray_start_global).magVecSquared());
04347         if( dist_to_surface_sq > (max_dist_from_camera * max_dist_from_camera) )
04348         {
04349                 return FALSE;
04350         }
04351 
04352         
04353         LLViewerRegion *regionp = gWorldp->getRegionFromPosGlobal(surface_pos_global);
04354         if (!regionp)
04355         {
04356                 llwarns << "Trying to add object outside of all known regions!" << llendl;
04357                 return FALSE;
04358         }
04359 
04360         
04361         LLVector3d              mouse_direction;
04362         mouse_direction.setVec( gViewerWindow->mouseDirectionGlobal( x, y ) );
04363 
04364         *region = regionp;
04365         *ray_start_region =     regionp->getPosRegionFromGlobal( ray_start_global );
04366         F32 near_clip = gCamera->getNear() + 0.01f;  
04367         *ray_start_region += gCamera->getAtAxis() * near_clip;
04368 
04369         if( bypass_sim_raycast )
04370         {
04371                 
04372                 *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global );  
04373         }
04374         else
04375         {
04376                 LLVector3d              ray_end_global = ray_start_global + (1.f + max_dist_from_camera) * mouse_direction;  
04377                 *ray_end_region = regionp->getPosRegionFromGlobal( ray_end_global );
04378         }
04379 
04380         return TRUE;
04381 }
04382 
04383 const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f);
04384 
04385 BOOL add_object( LLPCode pcode, S32 x, S32 y, U8 use_physics )
04386 {
04387         LLVector3 ray_start_region;
04388         LLVector3 ray_end_region;
04389         LLViewerRegion* regionp = NULL;
04390         BOOL b_hit_land = FALSE;
04391         S32 hit_face = -1;
04392         LLViewerObject* hit_obj = NULL;
04393         U8 state = 0;
04394         BOOL success = raycast_for_new_obj_pos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, ®ionp );
04395         if( !success )
04396         {
04397                 return FALSE;
04398         }
04399 
04400         if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
04401         {
04402                 
04403                 return FALSE;
04404         }
04405 
04406         if (NULL == regionp)
04407         {
04408                 llwarns << "regionp was NULL; aborting function." << llendl;
04409                 return FALSE;
04410         }
04411 
04412         if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)
04413         {
04414                 LLFirstUse::useSandbox();
04415         }
04416 
04417         
04418         LLQuaternion    rotation;
04419         LLVector3               scale = DEFAULT_OBJECT_SCALE;
04420         U8                              material = LL_MCODE_WOOD;
04421         BOOL                    create_selected = FALSE;
04422         LLVolumeParams  volume_params;
04423         
04424         switch (pcode) 
04425         {
04426         case LL_PCODE_LEGACY_GRASS:
04427                 
04428                 scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f),  1.f + ll_frand(2.f));
04429                 state = rand() % LLVOGrass::sMaxGrassSpecies;
04430                 break;
04431 
04432 
04433         case LL_PCODE_LEGACY_TREE:
04434         case LL_PCODE_TREE_NEW:
04435                 state = rand() % LLVOTree::sMaxTreeSpecies;
04436                 break;
04437 
04438         case LL_PCODE_SPHERE:
04439         case LL_PCODE_CONE:
04440         case LL_PCODE_CUBE:
04441         case LL_PCODE_CYLINDER:
04442         case LL_PCODE_TORUS:
04443         case LLViewerObject::LL_VO_SQUARE_TORUS:
04444         case LLViewerObject::LL_VO_TRIANGLE_TORUS:
04445         default:
04446                 create_selected = TRUE;
04447                 break;
04448         }
04449 
04450         
04451         if (gAudiop)
04452         {
04453                 F32 volume = gSavedSettings.getF32("AudioLevelUI");
04454                 gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume);
04455         }
04456 
04457         gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
04458         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
04459         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
04460         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
04461         gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
04462         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
04463         gMessageSystem->addU8Fast(_PREHASH_Material,    material);
04464 
04465         U32 flags = 0;          
04466         if (use_physics)
04467         {
04468                 flags |= FLAGS_USE_PHYSICS;
04469         }
04470         if (create_selected)
04471         {
04472                 flags |= FLAGS_CREATE_SELECTED;
04473         }
04474         gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags );
04475 
04476         LLPCode volume_pcode;   
04477         switch (pcode)
04478         {
04479         case LL_PCODE_SPHERE:
04480                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
04481 
04482                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
04483                 volume_params.setBeginAndEndS( 0.f, 1.f );
04484                 volume_params.setBeginAndEndT( 0.f, 1.f );
04485                 volume_params.setRatio  ( 1, 1 );
04486                 volume_params.setShear  ( 0, 0 );
04487                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04488                 volume_pcode = LL_PCODE_VOLUME;
04489                 break;
04490 
04491         case LL_PCODE_TORUS:
04492                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
04493 
04494                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE );
04495                 volume_params.setBeginAndEndS( 0.f, 1.f );
04496                 volume_params.setBeginAndEndT( 0.f, 1.f );
04497                 volume_params.setRatio  ( 1.f, 0.25f ); 
04498                 volume_params.setShear  ( 0, 0 );
04499                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04500                 volume_pcode = LL_PCODE_VOLUME;
04501                 break;
04502 
04503         case LLViewerObject::LL_VO_SQUARE_TORUS:
04504                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
04505 
04506                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE );
04507                 volume_params.setBeginAndEndS( 0.f, 1.f );
04508                 volume_params.setBeginAndEndT( 0.f, 1.f );
04509                 volume_params.setRatio  ( 1.f, 0.25f ); 
04510                 volume_params.setShear  ( 0, 0 );
04511                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04512                 volume_pcode = LL_PCODE_VOLUME;
04513                 break;
04514 
04515         case LLViewerObject::LL_VO_TRIANGLE_TORUS:
04516                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
04517 
04518                 volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE );
04519                 volume_params.setBeginAndEndS( 0.f, 1.f );
04520                 volume_params.setBeginAndEndT( 0.f, 1.f );
04521                 volume_params.setRatio  ( 1.f, 0.25f ); 
04522                 volume_params.setShear  ( 0, 0 );
04523                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04524                 volume_pcode = LL_PCODE_VOLUME;
04525                 break;
04526 
04527         case LL_PCODE_SPHERE_HEMI:
04528                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
04529                 
04530                 volume_params.setBeginAndEndT( 0.f, 0.5f );
04531                 volume_params.setRatio  ( 1, 1 );
04532                 volume_params.setShear  ( 0, 0 );
04533                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04534                 volume_pcode = LL_PCODE_VOLUME;
04535                 break;
04536 
04537         case LL_PCODE_CUBE:
04538                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
04539                 volume_params.setBeginAndEndS( 0.f, 1.f );
04540                 volume_params.setBeginAndEndT( 0.f, 1.f );
04541                 volume_params.setRatio  ( 1, 1 );
04542                 volume_params.setShear  ( 0, 0 );
04543                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04544                 volume_pcode = LL_PCODE_VOLUME;
04545                 break;
04546 
04547         case LL_PCODE_PRISM:
04548                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
04549                 volume_params.setBeginAndEndS( 0.f, 1.f );
04550                 volume_params.setBeginAndEndT( 0.f, 1.f );
04551                 volume_params.setRatio  ( 0, 1 );
04552                 volume_params.setShear  ( -0.5f, 0 );
04553                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04554                 volume_pcode = LL_PCODE_VOLUME;
04555                 break;
04556 
04557         case LL_PCODE_PYRAMID:
04558                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
04559                 volume_params.setBeginAndEndS( 0.f, 1.f );
04560                 volume_params.setBeginAndEndT( 0.f, 1.f );
04561                 volume_params.setRatio  ( 0, 0 );
04562                 volume_params.setShear  ( 0, 0 );
04563                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04564                 volume_pcode = LL_PCODE_VOLUME;
04565                 break;
04566 
04567         case LL_PCODE_TETRAHEDRON:
04568                 volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE );
04569                 volume_params.setBeginAndEndS( 0.f, 1.f );
04570                 volume_params.setBeginAndEndT( 0.f, 1.f );
04571                 volume_params.setRatio  ( 0, 0 );
04572                 volume_params.setShear  ( 0, 0 );
04573                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04574                 volume_pcode = LL_PCODE_VOLUME;
04575                 break;
04576 
04577         case LL_PCODE_CYLINDER:
04578                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
04579                 volume_params.setBeginAndEndS( 0.f, 1.f );
04580                 volume_params.setBeginAndEndT( 0.f, 1.f );
04581                 volume_params.setRatio  ( 1, 1 );
04582                 volume_params.setShear  ( 0, 0 );
04583                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04584                 volume_pcode = LL_PCODE_VOLUME;
04585                 break;
04586 
04587         case LL_PCODE_CYLINDER_HEMI:
04588                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
04589                 volume_params.setBeginAndEndS( 0.25f, 0.75f );
04590                 volume_params.setBeginAndEndT( 0.f, 1.f );
04591                 volume_params.setRatio  ( 1, 1 );
04592                 volume_params.setShear  ( 0, 0 );
04593                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04594                 volume_pcode = LL_PCODE_VOLUME;
04595                 break;
04596 
04597         case LL_PCODE_CONE:
04598                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
04599                 volume_params.setBeginAndEndS( 0.f, 1.f );
04600                 volume_params.setBeginAndEndT( 0.f, 1.f );
04601                 volume_params.setRatio  ( 0, 0 );
04602                 volume_params.setShear  ( 0, 0 );
04603                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04604                 volume_pcode = LL_PCODE_VOLUME;
04605                 break;
04606 
04607         case LL_PCODE_CONE_HEMI:
04608                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
04609                 volume_params.setBeginAndEndS( 0.25f, 0.75f );
04610                 volume_params.setBeginAndEndT( 0.f, 1.f );
04611                 volume_params.setRatio  ( 0, 0 );
04612                 volume_params.setShear  ( 0, 0 );
04613                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
04614                 volume_pcode = LL_PCODE_VOLUME;
04615                 break;
04616 
04617         default:
04618                 LLVolumeMessage::packVolumeParams(0, gMessageSystem);
04619                 volume_pcode = pcode;
04620                 break;
04621         }
04622         gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode);
04623 
04624         gMessageSystem->addVector3Fast(_PREHASH_Scale,                  scale );
04625         gMessageSystem->addQuatFast(_PREHASH_Rotation,                  rotation );
04626         gMessageSystem->addVector3Fast(_PREHASH_RayStart,               ray_start_region );
04627         gMessageSystem->addVector3Fast(_PREHASH_RayEnd,                 ray_end_region );
04628         gMessageSystem->addU8Fast(_PREHASH_BypassRaycast,               (U8)b_hit_land );
04629         gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE );
04630         gMessageSystem->addU8Fast(_PREHASH_State, state);
04631 
04632         
04633         
04634         
04635         LLUUID ray_target_id;
04636         if( hit_obj )
04637         {
04638                 ray_target_id = hit_obj->getID();
04639         }
04640         else
04641         {
04642                 ray_target_id.setNull();
04643         }
04644         gMessageSystem->addUUIDFast(_PREHASH_RayTargetID,                       ray_target_id );
04645         
04646         
04647         gMessageSystem->sendReliable(regionp->getHost());
04648 
04649         
04650         if (create_selected)
04651         {
04652                 gSelectMgr->deselectAll();
04653                 gViewerWindow->getWindow()->incBusyCount();
04654         }
04655 
04656         
04657         LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
04658         effectp->setSourceObject(gAgent.getAvatarObject());
04659         effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region));
04660         effectp->setDuration(LL_HUD_DUR_SHORT);
04661         effectp->setColor(LLColor4U(gAgent.getEffectColor()));
04662 
04663         gViewerStats->incStat(LLViewerStats::ST_CREATE_COUNT);
04664 
04665         return TRUE;
04666 }
04667 
04668 
04669 
04670 #if LL_WINDOWS
04671 void create_console()
04672 {
04673         int h_con_handle;
04674         long l_std_handle;
04675 
04676         CONSOLE_SCREEN_BUFFER_INFO coninfo;
04677         FILE *fp;
04678 
04679         
04680         AllocConsole();
04681 
04682         
04683         GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
04684         coninfo.dwSize.Y = MAX_CONSOLE_LINES;
04685         SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
04686 
04687         
04688         l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
04689         h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
04690         fp = _fdopen( h_con_handle, "w" );
04691         *stdout = *fp;
04692         setvbuf( stdout, NULL, _IONBF, 0 );
04693 
04694         
04695         l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE);
04696         h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
04697         fp = _fdopen( h_con_handle, "r" );
04698         *stdin = *fp;
04699         setvbuf( stdin, NULL, _IONBF, 0 );
04700 
04701         
04702         l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE);
04703         h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
04704         fp = _fdopen( h_con_handle, "w" );
04705         *stderr = *fp;
04706         setvbuf( stderr, NULL, _IONBF, 0 );
04707 }
04708 #endif
04709 
04710 
04711 
04712 
04713 
04714 
04715 
04716 
04717 
04718 
04719 
04720 BOOL    gVectorizePerfTest      = TRUE;
04721 BOOL    gVectorizeEnable        = FALSE;
04722 U32             gVectorizeProcessor     = 0;
04723 BOOL    gVectorizeSkin          = FALSE;
04724 
04725 void update_vector_performances(void)
04726 {
04727         char *vp;
04728         
04729         switch(gVectorizeProcessor)
04730         {
04731                 case 2: vp = "SSE2"; break;                                     
04732                 case 1: vp = "SSE"; break;
04733                 default: vp = "COMPILER DEFAULT"; break;
04734         }
04735         llinfos << "Vectorization         : " << ( gVectorizeEnable ? "ENABLED" : "DISABLED" ) << llendl ;
04736         llinfos << "Vector Processor      : " << vp << llendl ;
04737         llinfos << "Vectorized Skinning   : " << ( gVectorizeSkin ? "ENABLED" : "DISABLED" ) << llendl ;
04738         
04739         if(gVectorizeEnable && gVectorizeSkin)
04740         {
04741                 switch(gVectorizeProcessor)
04742                 {
04743                         case 2:
04744                                 LLViewerJointMesh::sUpdateGeometryFunc = &LLViewerJointMesh::updateGeometrySSE2;
04745                                 break;
04746                         case 1:
04747                                 LLViewerJointMesh::sUpdateGeometryFunc = &LLViewerJointMesh::updateGeometrySSE;
04748                                 break;
04749                         default:
04750                                 LLViewerJointMesh::sUpdateGeometryFunc = &LLViewerJointMesh::updateGeometryVectorized;
04751                                 break;
04752                 }
04753         }
04754         else
04755         {
04756                 LLViewerJointMesh::sUpdateGeometryFunc = &LLViewerJointMesh::updateGeometryOriginal;
04757         }
04758 }
04759 
04760 
04761 class LLVectorizationEnableListener: public LLSimpleListener
04762 {
04763         bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
04764         {
04765                 gVectorizeEnable = event->getValue().asBoolean();
04766                 update_vector_performances();
04767                 return true;
04768         }
04769 };
04770 static LLVectorizationEnableListener vectorization_enable_listener;
04771 
04772 class LLVectorizeSkinListener: public LLSimpleListener
04773 {
04774         bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
04775         {
04776                 gVectorizeSkin = event->getValue().asBoolean();
04777                 update_vector_performances();
04778                 return true;
04779         }
04780 };
04781 static LLVectorizeSkinListener vectorize_skin_listener;
04782 
04783 class LLVectorProcessorListener: public LLSimpleListener
04784 {
04785         bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
04786         {
04787                 gVectorizeProcessor = event->getValue().asInteger();
04788                 update_vector_performances();
04789                 return true;
04790         }
04791 };
04792 static LLVectorProcessorListener vector_processor_listener;
04793 
04794 
04795 
04796 void saved_settings_to_globals()
04797 {
04798         LLBUTTON_H_PAD          = gSavedSettings.getS32("ButtonHPad");
04799         LLBUTTON_V_PAD          = gSavedSettings.getS32("ButtonVPad");
04800         BTN_HEIGHT_SMALL        = gSavedSettings.getS32("ButtonHeightSmall");
04801         BTN_HEIGHT                      = gSavedSettings.getS32("ButtonHeight");
04802 
04803         MENU_BAR_HEIGHT         = gSavedSettings.getS32("MenuBarHeight");
04804         MENU_BAR_WIDTH          = gSavedSettings.getS32("MenuBarWidth");
04805         STATUS_BAR_HEIGHT       = gSavedSettings.getS32("StatusBarHeight");
04806 
04807         LLCOMBOBOX_HEIGHT       = BTN_HEIGHT - 2;
04808         LLCOMBOBOX_WIDTH        = 128;
04809 
04810         LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
04811 
04812         LLVOSky::sNighttimeBrightness           = gSavedSettings.getF32("RenderNightBrightness");
04813         
04814         LLImageGL::sGlobalUseAnisotropic        = gSavedSettings.getBOOL("RenderAnisotropic");
04815         LLVOVolume::sLODFactor                          = gSavedSettings.getF32("RenderVolumeLODFactor");
04816         LLVOVolume::sDistanceFactor                     = 1.f-LLVOVolume::sLODFactor * 0.1f;
04817         LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
04818         LLVOTree::sTreeFactor                           = gSavedSettings.getF32("RenderTreeLODFactor");
04819         LLVOAvatar::sLODFactor                          = gSavedSettings.getF32("RenderAvatarLODFactor");
04820         LLVOAvatar::sMaxVisible                         = gSavedSettings.getS32("RenderAvatarMaxVisible");
04821         LLVOAvatar::sVisibleInFirstPerson       = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
04822         
04823         LLFolderView::sAutoOpenTime                     = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
04824         LLToolBar::sInventoryAutoOpenTime       = gSavedSettings.getF32("InventoryAutoOpenDelay");
04825         LLSelectMgr::sRectSelectInclusive       = gSavedSettings.getBOOL("RectangleSelectInclusive");
04826         LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
04827         LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
04828 
04829         gFrameStats.setTrackStats(gSavedSettings.getBOOL("StatsSessionTrackFrameStats"));
04830         gAgentPilot.mNumRuns            = gSavedSettings.getS32("StatsNumRuns");
04831         gAgentPilot.mQuitAfterRuns      = gSavedSettings.getBOOL("StatsQuitAfterRuns");
04832         gAgent.mHideGroupTitle          = gSavedSettings.getBOOL("RenderHideGroupTitle");
04833 
04834         gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
04835         gAllowIdleAFK = gSavedSettings.getBOOL("AllowIdleAFK");
04836         gAFKTimeout = gSavedSettings.getF32("AFKTimeout");
04837         gMouseSensitivity = gSavedSettings.getF32("MouseSensitivity");
04838         gInvertMouse = gSavedSettings.getBOOL("InvertMouse");
04839         gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
04840         gMapScale = gSavedSettings.getF32("MapScale");
04841         gMiniMapScale = gSavedSettings.getF32("MiniMapScale");
04842         gHandleKeysAsync = gSavedSettings.getBOOL("AsyncKeyboard");
04843         LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
04844 
04845 #if LL_VECTORIZE
04846         if (gSysCPU.hasAltivec())
04847         {
04848                 gSavedSettings.setBOOL("VectorizeEnable", TRUE );
04849                 gSavedSettings.setU32("VectorizeProcessor", 0 );
04850         }
04851         else
04852         if (gSysCPU.hasSSE2())
04853         {
04854                 gSavedSettings.setBOOL("VectorizeEnable", TRUE );
04855                 gSavedSettings.setU32("VectorizeProcessor", 2 );
04856         }
04857         else
04858         if (gSysCPU.hasSSE())
04859         {
04860                 gSavedSettings.setBOOL("VectorizeEnable", TRUE );
04861                 gSavedSettings.setU32("VectorizeProcessor", 1 );
04862         }
04863         else
04864         {
04865                 
04866                 gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
04867                 gSavedSettings.setBOOL("VectorizeEnable", FALSE );
04868                 gSavedSettings.setU32("VectorizeProcessor", 0 );
04869                 gSavedSettings.setBOOL("VectorizeSkin", FALSE);
04870         }
04871 #else
04872         
04873         gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
04874         gSavedSettings.setBOOL("VectorizeEnable", FALSE );
04875         gSavedSettings.setU32("VectorizeProcessor", 0 );
04876         gSavedSettings.setBOOL("VectorizeSkin", FALSE);
04877 #endif
04878 
04879         gVectorizePerfTest = gSavedSettings.getBOOL("VectorizePerfTest");
04880         gVectorizeEnable = gSavedSettings.getBOOL("VectorizeEnable");
04881         gVectorizeProcessor = gSavedSettings.getU32("VectorizeProcessor");
04882         gVectorizeSkin = gSavedSettings.getBOOL("VectorizeSkin");
04883         update_vector_performances();
04884 
04885         
04886         gCrashBehavior = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING);
04887 
04888         
04889         gSavedSettings.setBOOL("PTTCurrentlyEnabled", gSavedSettings.getBOOL("EnablePushToTalk"));
04890 
04891         settings_setup_listeners();
04892         
04893         
04894         gSavedSettings.getControl("VectorizeEnable")->addListener(&vectorization_enable_listener);
04895         gSavedSettings.getControl("VectorizeProcessor")->addListener(&vector_processor_listener);
04896         gSavedSettings.getControl("VectorizeSkin")->addListener(&vectorize_skin_listener);
04897 
04898         
04899 }
04900 
04901 void cleanup_saved_settings()
04902 {
04903         gSavedSettings.setBOOL("MouseSun", FALSE);
04904 
04905         gSavedSettings.setBOOL("FlyBtnState", FALSE);
04906 
04907         gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
04908         gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE);
04909         gSavedSettings.setBOOL("BuildBtnState", FALSE);
04910 
04911         gSavedSettings.setBOOL("UseEnergy", TRUE);                              
04912 
04913         gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
04914                 
04915         gSavedSettings.setBOOL("AllowIdleAFK", gAllowIdleAFK);
04916         gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
04917         
04918         if (!gNoRender)
04919         {
04920                 if (gDebugView)
04921                 {
04922                         gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
04923                         gSavedSettings.setBOOL("ShowDebugStats", gDebugView->mStatViewp->getVisible());
04924                 }
04925         }
04926 
04927         
04928         
04929         BOOL fullscreen = gViewerWindow->mWindow->getFullscreen();
04930         BOOL maximized = gViewerWindow->mWindow->getMaximized();
04931         if (!fullscreen && !maximized)
04932         {
04933                 LLCoordScreen window_pos;
04934 
04935                 if (gViewerWindow->mWindow->getPosition(&window_pos))
04936                 {
04937                         gSavedSettings.setS32("WindowX", window_pos.mX);
04938                         gSavedSettings.setS32("WindowY", window_pos.mY);
04939                 }
04940         }
04941 
04942         gSavedSettings.setF32("MapScale", gMapScale );
04943         gSavedSettings.setF32("MiniMapScale", gMiniMapScale );
04944         gSavedSettings.setBOOL("AsyncKeyboard", gHandleKeysAsync);
04945         gSavedSettings.setBOOL("ShowHoverTips", LLHoverView::sShowHoverTips);
04946 
04947         
04948         if (gAgent.mInitialized)
04949         {
04950                 gSavedSettings.setF32("RenderFarClip", gAgent.mDrawDistance);
04951         }
04952 
04953         gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, gCrashBehavior);
04954 }
04955 
04956 
04957 void callback_cache_name(const LLUUID& id, const char* firstname, const char* lastname, BOOL is_group, void* data)
04958 {
04959         LLNameListCtrl::refreshAll(id, firstname, lastname, is_group);
04960         LLNameBox::refreshAll(id, firstname, lastname, is_group);
04961         LLNameEditor::refreshAll(id, firstname, lastname, is_group);
04962         
04963         
04964         
04965         dialog_refresh_all();
04966 }
04967 
04968 
04969 void write_debug(const std::string& str)
04970 {
04971         write_debug(str.c_str());
04972 }
04973 
04974 void write_debug(const char *str)
04975 {
04976         if (!gDebugFile)
04977         {
04978                 std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
04979                 llinfos << "Opening debug file " << debug_filename << llendl;
04980                 gDebugFile = LLFile::fopen(debug_filename.c_str(), "w");                
04981         if (!gDebugFile)
04982         {
04983                     llinfos << "Opening debug file " << debug_filename << " failed. Using stderr." << llendl;
04984             gDebugFile = stderr;
04985         }
04986         }
04987         fputs(str, gDebugFile);
04988         fflush(gDebugFile);
04989 }
04990 
04991 void close_debug()
04992 {
04993         if (gDebugFile)
04994         {
04995                 fclose(gDebugFile);
04996         }
04997         gDebugFile = NULL;
04998 }
04999 
05000 void print_agent_nvpairs(void*)
05001 {
05002         LLViewerObject *objectp;
05003 
05004         llinfos << "Agent Name Value Pairs" << llendl;
05005 
05006         objectp = gObjectList.findObject(gAgentID);
05007         if (objectp)
05008         {
05009                 objectp->printNameValuePairs();
05010         }
05011         else
05012         {
05013                 llinfos << "Can't find agent object" << llendl;
05014         }
05015 
05016         llinfos << "Camera at " << gAgent.getCameraPositionGlobal() << llendl;
05017 }
05018 
05019 
05020 void reset_statistics()
05021 {
05022         gPipeline.resetFrameStats();    
05023         if (LLSurface::sTextureUpdateTime)
05024         {
05025                 LLSurface::sTexelsUpdatedPerSecStat.addValue(0.001f*(LLSurface::sTexelsUpdated / LLSurface::sTextureUpdateTime));
05026                 LLSurface::sTexelsUpdated = 0;
05027                 LLSurface::sTextureUpdateTime = 0.f;
05028         }
05029 }
05030 
05031 
05032 void output_statistics(void*)
05033 {
05034         llinfos << "Number of orphans: " << gObjectList.getOrphanCount() << llendl;
05035         llinfos << "Number of dead objects: " << gObjectList.mNumDeadObjects << llendl;
05036         llinfos << "Num images: " << gImageList.getNumImages() << llendl;
05037         llinfos << "Texture usage: " << LLImageGL::sGlobalTextureMemory << llendl;
05038         llinfos << "Texture working set: " << LLImageGL::sBoundTextureMemory << llendl;
05039         llinfos << "Raw usage: " << LLImageRaw::sGlobalRawMemory << llendl;
05040         llinfos << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << llendl;
05041         llinfos << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << llendl;
05042         llinfos << "Number of lights: " << gPipeline.getLightCount() << llendl;
05043 
05044         llinfos << "Memory Usage:" << llendl;
05045         llinfos << "--------------------------------" << llendl;
05046         llinfos << "Pipeline:" << llendl;
05047         llinfos << llendl;
05048 
05049 #if LL_SMARTHEAP
05050         llinfos << "--------------------------------" << llendl;
05051         {
05052                 llinfos << "sizeof(LLVOVolume) = " << sizeof(LLVOVolume) << llendl;
05053 
05054                 U32 total_pool_size = 0;
05055                 U32 total_used_size = 0;
05056                 MEM_POOL_INFO pool_info;
05057                 MEM_POOL_STATUS pool_status;
05058                 U32 pool_num = 0;
05059                 for(pool_status = MemPoolFirst( &pool_info, 1 ); 
05060                         pool_status != MEM_POOL_END; 
05061                         pool_status = MemPoolNext( &pool_info, 1 ) )
05062                 {
05063                         llinfos << "Pool #" << pool_num << llendl;
05064                         if( MEM_POOL_OK != pool_status )
05065                         {
05066                                 llwarns << "Pool not ok" << llendl;
05067                                 continue;
05068                         }
05069 
05070                         llinfos << "Pool blockSizeFS " << pool_info.blockSizeFS
05071                                 << " pageSize " << pool_info.pageSize
05072                                 << llendl;
05073 
05074                         U32 pool_count = MemPoolCount(pool_info.pool);
05075                         llinfos << "Blocks " << pool_count << llendl;
05076 
05077                         U32 pool_size = MemPoolSize( pool_info.pool );
05078                         if( pool_size == MEM_ERROR_RET )
05079                         {
05080                                 llinfos << "MemPoolSize() failed (" << pool_num << ")" << llendl;
05081                         }
05082                         else
05083                         {
05084                                 llinfos << "MemPool Size " << pool_size / 1024 << "K" << llendl;
05085                         }
05086 
05087                         total_pool_size += pool_size;
05088 
05089                         if( !MemPoolLock( pool_info.pool ) )
05090                         {
05091                                 llinfos << "MemPoolLock failed (" << pool_num << ") " << llendl;
05092                                 continue;
05093                         }
05094 
05095                         U32 used_size = 0; 
05096                         MEM_POOL_ENTRY entry;
05097                         entry.entry = NULL;
05098                         while( MemPoolWalk( pool_info.pool, &entry ) == MEM_POOL_OK )
05099                         {
05100                                 if( entry.isInUse )
05101                                 {
05102                                         used_size += entry.size;
05103                                 }
05104                         }
05105 
05106                         MemPoolUnlock( pool_info.pool );
05107 
05108                         llinfos << "MemPool Used " << used_size/1024 << "K" << llendl;
05109                         total_used_size += used_size;
05110                         pool_num++;
05111                 }
05112                 
05113                 llinfos << "Total Pool Size " << total_pool_size/1024 << "K" << llendl;
05114                 llinfos << "Total Used Size " << total_used_size/1024 << "K" << llendl;
05115 
05116         }
05117 #endif
05118 
05119         llinfos << "--------------------------------" << llendl;
05120         llinfos << "Avatar Memory (partly overlaps with above stats):" << llendl;
05121         gTexStaticImageList.dumpByteCount();
05122         LLVOAvatar::dumpScratchTextureByteCount();
05123         LLTexLayerSetBuffer::dumpTotalByteCount();
05124         LLVOAvatar::dumpTotalLocalTextureByteCount();
05125         LLTexLayerParamAlpha::dumpCacheByteCount();
05126         LLVOAvatar::dumpBakedStatus();
05127 
05128         llinfos << llendl;
05129 
05130         llinfos << "Object counts:" << llendl;
05131         S32 i;
05132         S32 obj_counts[256];
05133 
05134         for (i = 0; i < 256; i++)
05135         {
05136                 obj_counts[i] = 0;
05137         }
05138         for (i = 0; i < gObjectList.getNumObjects(); i++)
05139         {
05140                 LLViewerObject *objectp = gObjectList.getObject(i);
05141                 if (objectp)
05142                 {
05143                         obj_counts[objectp->getPCode()]++;
05144                 }
05145         }
05146         for (i = 0; i < 256; i++)
05147         {
05148                 if (obj_counts[i])
05149                 {
05150                         llinfos << LLPrimitive::pCodeToString(i) << ":" << obj_counts[i] << llendl;
05151                 }
05152         }
05153 
05154         
05155 
05156 
05157 
05158 
05159 
05160 
05161 
05162 
05163 
05164 
05165 
05166 
05167 
05168 
05169 
05170 
05171 
05172 
05173 
05174 
05175 
05176 
05177         
05178 
05179 
05180 
05181 
05182 
05183 
05184 
05185 
05186 
05187 
05188 
05189 
05190 
05191 
05192 
05193 
05194 
05195 
05196 
05197 
05198 
05199 
05200 
05201 
05202 
05203 
05204 
05205 
05206 
05207 
05208 
05209 
05210 
05211 
05212 
05213 
05214 
05215 
05216 
05217 
05218 
05219 
05220 
05221 
05222 }
05223 
05224 class ViewerStatsResponder : public LLHTTPClient::Responder
05225 {
05226 public:
05227     ViewerStatsResponder() { }
05228 
05229     void error(U32 statusNum, const std::string& reason)
05230     {
05231                 llinfos << "ViewerStatsResponder::error " << statusNum << " "
05232                                 << reason << llendl;
05233     }
05234 
05235     void result(const LLSD& content)
05236     {
05237                 llinfos << "ViewerStatsResponder::result" << llendl;
05238         }
05239 };
05240 
05241 
05242 
05243 
05244 
05245 
05246 
05247 
05248 
05249 
05250 void send_stats()
05251 {
05252         
05253         
05254         
05255         
05256 
05257         
05258         if (!gAgent.getRegion() || gNoRender)
05259         {
05260                 return;
05261         }
05262 
05263         LLSD body;
05264         std::string url = gAgent.getRegion()->getCapability("ViewerStats");
05265 
05266         if (url.empty()) {
05267                 llwarns << "Could not get ViewerStats capability" << llendl;
05268                 return;
05269         }
05270         
05271         body["session_id"] = gAgentSessionID;
05272         
05273         LLSD &agent = body["agent"];
05274         
05275         time_t ltime;
05276         time(<ime);
05277         F32 run_time = F32(LLFrameTimer::getElapsedSeconds());
05278 
05279         agent["start_time"] = ltime - run_time;
05280         agent["run_time"] = run_time;
05281         
05282         agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32();
05283         agent["version"] = gCurrentVersion;
05284         agent["language"] = gSavedSettings.getString("Language");
05285         
05286         agent["sim_fps"] = ((F32) gFrameCount - gSimFrames) /
05287                 (F32) (gRenderStartTime.getElapsedTimeF32() - gSimLastTime);
05288 
05289         gSimLastTime = gRenderStartTime.getElapsedTimeF32();
05290         gSimFrames   = (F32) gFrameCount;
05291 
05292         agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
05293         agent["ping"] = gAvgSimPing;
05294         agent["meters_traveled"] = gAgent.getDistanceTraveled();
05295         agent["regions_visited"] = gAgent.getRegionsVisited();
05296         agent["mem_use"] = getCurrentRSS() / 1024.0;
05297 
05298         LLSD &system = body["system"];
05299         
05300         system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();
05301         system["os"] = gSysOS.getOSString();
05302         system["cpu"] = gSysCPU.getCPUString();
05303 
05304         std::string gpu_desc = llformat(
05305                 "%-6s Class %d ",
05306                 gGLManager.mGLVendorShort.substr(0,6).c_str(),
05307                 gFeatureManagerp->getGPUClass())
05308                 + gFeatureManagerp->getGPUString();
05309 
05310         system["gpu"] = gpu_desc;
05311         system["gpu_class"] = gFeatureManagerp->getGPUClass();
05312         system["gpu_vendor"] = gGLManager.mGLVendorShort;
05313         system["gpu_version"] = gGLManager.mDriverVersionVendorString;
05314 
05315         LLSD &download = body["downloads"];
05316 
05317         download["world_kbytes"] = gTotalWorldBytes / 1024.0;
05318         download["object_kbytes"] = gTotalObjectBytes / 1024.0;
05319         download["texture_kbytes"] = gTotalTextureBytes / 1024.0;
05320 
05321         LLSD &in = body["stats"]["net"]["in"];
05322 
05323         in["kbytes"] = gMessageSystem->mTotalBytesIn / 1024.0;
05324         in["packets"] = (S32) gMessageSystem->mPacketsIn;
05325         in["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsIn;
05326         in["savings"] = (gMessageSystem->mUncompressedBytesIn -
05327                                          gMessageSystem->mCompressedBytesIn) / 1024.0;
05328         
05329         LLSD &out = body["stats"]["net"]["out"];
05330         
05331         out["kbytes"] = gMessageSystem->mTotalBytesOut / 1024.0;
05332         out["packets"] = (S32) gMessageSystem->mPacketsOut;
05333         out["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsOut;
05334         out["savings"] = (gMessageSystem->mUncompressedBytesOut -
05335                                           gMessageSystem->mCompressedBytesOut) / 1024.0;
05336 
05337         LLSD &fail = body["stats"]["failures"];
05338 
05339         fail["send_packet"] = (S32) gMessageSystem->mSendPacketFailureCount;
05340         fail["dropped"] = (S32) gMessageSystem->mDroppedPackets;
05341         fail["resent"] = (S32) gMessageSystem->mResentPackets;
05342         fail["failed_resends"] = (S32) gMessageSystem->mFailedResendPackets;
05343         fail["off_circuit"] = (S32) gMessageSystem->mOffCircuitPackets;
05344         fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets;
05345 
05346         gViewerStats->addToMessage(body);
05347 
05348         LLHTTPClient::post(url, body, new ViewerStatsResponder());
05349 }
05350 
05351 #if !LL_WINDOWS
05352 
05353 void signal_handlers(S32 s)
05354 {
05355         release_signals();
05356 
05357         
05358         if(SIGTERM == s)
05359         {
05360                 
05361                 app_force_quit(NULL);
05362                 return;
05363         }
05364 
05365 # if LL_LINUX || LL_SOLARIS
05366         
05367         
05368         llwarns << "*** Caught signal " << s << llendl;
05369 # endif
05370 
05371         if (gCrashCallback)
05372         {
05373                 gCrashCallback();
05374         }
05375 }
05376 #endif
05377 
05378 
05379 void catch_signals()
05380 {
05381 #if LL_WINDOWS
05382         
05383         LLWinDebug::setupExceptionHandler();
05384         return;
05385 #else
05386         
05387 
05388 
05389         
05390         signal(SIGILL, signal_handlers);
05391         signal(SIGTRAP, signal_handlers);
05392         if (being_debugged())
05393         {
05394                 
05395                 
05396                 signal(SIGABRT, SIG_DFL);
05397         } else {
05398                 signal(SIGABRT, signal_handlers);
05399         }
05400         signal(SIGFPE, signal_handlers);
05401         signal(SIGBUS, signal_handlers);
05402         signal(SIGSEGV, signal_handlers);
05403         signal(SIGSYS, signal_handlers);
05404 
05405         
05406 #if !LL_LINUX && !LL_SOLARIS
05407         signal(SIGEMT, signal_handlers);
05408 #endif
05409 
05410         
05411         signal(SIGTERM, signal_handlers);
05412 
05413 #endif // LL_WINDOWS
05414 }
05415 
05416 #if !LL_WINDOWS
05417 void release_signals()
05418 {
05419         signal(SIGTERM, SIG_DFL);
05420         signal(SIGABRT, SIG_DFL);
05421         signal(SIGILL, SIG_DFL);
05422         signal(SIGFPE, SIG_DFL);
05423         signal(SIGSEGV, SIG_DFL);
05424 
05425 #ifdef SIGBUS
05426         signal(SIGBUS, SIG_DFL);
05427 #endif
05428 
05429 #ifdef SIGSYS
05430         signal(SIGSYS, SIG_DFL);
05431 #endif
05432 }
05433 #endif // !LL_WINDOWS
05434 
05435 void purge_cache()
05436 {
05437         llinfos << "Purging Texture Cache..." << llendl;
05438         gTextureCache->purgeCache(LL_PATH_CACHE);
05439         llinfos << "Purging Cache..." << llendl;
05440         std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
05441         gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
05442 }
05443 
05444 int parse_args(int argc, char **argv)
05445 {
05446         
05447         
05448         LLString ip_string;
05449         S32 j;
05450 
05451         for (j = 1; j < argc; j++) 
05452         {
05453                 gArgs += argv[j];
05454                 gArgs += " ";
05455 
05456                 if ((!strcmp(argv[j], "-port")) && (++j < argc)) 
05457                 {
05458                         sscanf(argv[j], "%u", &(gAgent.mViewerPort));
05459                 }
05460                 else if ((!strcmp(argv[j], "-drop")) && (++j < argc)) 
05461                 {
05462                         sscanf(argv[j], "%f", &gPacketDropPercentage);
05463                 }
05464                 else if ((!strcmp(argv[j], "-inbw")) && (++j < argc))
05465                 {
05466                         sscanf(argv[j], "%f", &gInBandwidth);
05467                 }
05468                 else if ((!strcmp(argv[j], "-outbw")) && (++j < argc))
05469                 {
05470                         sscanf(argv[j], "%f", &gOutBandwidth);
05471                 }
05472                 else if (!strcmp(argv[j], "--aditi"))
05473                 {
05474                         gUserServerChoice = USERSERVER_ADITI;
05475                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05476                 }
05477                 else if (!strcmp(argv[j], "--agni"))
05478                 {
05479                         gUserServerChoice = USERSERVER_AGNI;
05480                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05481                 }
05482                 else if (!strcmp(argv[j], "--dmz"))
05483                 {
05484                         gUserServerChoice = USERSERVER_DMZ;
05485                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05486                 }
05487                 else if (!strcmp(argv[j], "--siva"))
05488                 {
05489                         gUserServerChoice = USERSERVER_SIVA;
05490                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05491                 }
05492                 else if (!strcmp(argv[j], "--shakti"))
05493                 {
05494                         gUserServerChoice = USERSERVER_SHAKTI;
05495                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05496                 }
05497                 else if (!strcmp(argv[j], "--durga"))
05498                 {
05499                         gUserServerChoice = USERSERVER_DURGA;
05500                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05501                 }
05502                 else if (!strcmp(argv[j], "--soma"))
05503                 {
05504                         gUserServerChoice = USERSERVER_SOMA;
05505                         snprintf(gUserServerName, MAX_STRING, "%s", gUserServerDomainName[gUserServerChoice].mName);            
05506                 }
05507                 else if (!strcmp(argv[j], "--ganga"))
05508                 {
05509                         gUserServerChoice = USERSERVER_GANGA;
05510                         sprintf(gUserServerName,"%s", gUserServerDomainName[gUserServerChoice].mName);
05511                 }
05512                 else if (!strcmp(argv[j], "--vaak"))
05513                 {
05514                         gUserServerChoice = USERSERVER_VAAK;
05515                         sprintf(gUserServerName,"%s", gUserServerDomainName[gUserServerChoice].mName);
05516                 }
05517                 else if (!strcmp(argv[j], "--uma"))
05518                 {
05519                         gUserServerChoice = USERSERVER_UMA;
05520                         sprintf(gUserServerName,"%s", gUserServerDomainName[gUserServerChoice].mName);
05521                 }
05522                 else if (!strcmp(argv[j], "-user") && (++j < argc)) 
05523                 {
05524                         if (!strcmp(argv[j], "-"))
05525                         {
05526                                 gUserServerChoice = USERSERVER_LOCAL;
05527                                 snprintf(gUserServerName, MAX_STRING, "%s", LOOPBACK_ADDRESS_STRING);           
05528                         }
05529                         else
05530                         {
05531                                 gUserServerChoice = USERSERVER_OTHER;
05532                                 ip_string.assign( argv[j] );
05533                                 LLString::trim(ip_string);
05534                                 snprintf(gUserServerName, MAX_STRING, "%s", ip_string.c_str());         
05535                         }
05536                 }
05537                 else if (!strcmp(argv[j], "-loginuri") && (++j < argc))
05538                 {
05539                         gLoginURIs.push_back(utf8str_trim(argv[j]));
05540                 }
05541                 else if (!strcmp(argv[j], "-helperuri") && (++j < argc))
05542                 {
05543                         gHelperURI = argv[j];
05544                         gHelperURI = utf8str_trim(gHelperURI);
05545                 }
05546                 else if (!strcmp(argv[j], "-debugviews"))
05547                 {
05548                         LLView::sDebugRects = TRUE;
05549                 }
05550                 else if (!strcmp(argv[j], "-skin") && (++j < argc))
05551                 {
05552                         std::string folder(argv[j]);
05553                         gDirUtilp->setSkinFolder(folder);
05554                 }
05555                 else if (!strcmp(argv[j], "-autologin") || !strcmp(argv[j], "--autologin")) 
05556                 {
05557                         gAutoLogin = TRUE;
05558                 }
05559                 else if (!strcmp(argv[j], "-quitafter") && (++j < argc))
05560                 {
05561                         gQuitAfterSeconds = (F32)atof(argv[j]);
05562                 }
05563                 else if (!strcmp(argv[j], "-rotate"))
05564                 {
05565                         gRotateRight = TRUE;
05566                 }
05567 
05568 
05569                         
05570 
05571 
05572                 else if (!strcmp(argv[j], "-noaudio"))
05573                 {
05574                         gUseAudio = FALSE;
05575                 }
05576                 else if (!strcmp(argv[j], "-nosound"))  
05577                 {
05578                         gUseAudio = FALSE;
05579                 }
05580                 else if (!strcmp(argv[j], "-nofmod"))
05581                 {
05582                         gUseFMOD = FALSE;
05583                 }
05584                 else if (!strcmp(argv[j], "-noprobe"))
05585                 {
05586                         gProbeHardware = FALSE;
05587                 }
05588                 else if (!strcmp(argv[j], "-noquicktime"))
05589                 {
05590                         
05591                         
05592                         gUseQuickTime = false;
05593                 }
05594                 else if (!strcmp(argv[j], "-nopreload"))
05595                 {
05596                         
05597                         
05598                         gPreloadSounds = false;
05599                         gPreloadImages = false;
05600                 }
05601                 else if (!strcmp(argv[j], "-purge"))
05602                 {
05603                         purge_cache();
05604                 }
05605                 else if(!strcmp(argv[j], "-noinvlib"))
05606                 {
05607                         gRequestInventoryLibrary = FALSE;
05608                 }
05609                 else if (!strcmp(argv[j], "-log"))
05610                 {
05611                         gLogMessages = TRUE;
05612                         continue;
05613                 }
05614                 else if (!strcmp(argv[j], "-logfile") && (++j < argc)) 
05615                 {
05616                         
05617                         char logfile[256];      
05618                         sscanf(argv[j], "%255s", logfile);      
05619                         llinfos << "Setting log file to " << logfile << llendl;
05620                         LLFile::remove(logfile);
05621                         LLError::logToFile(logfile);
05622                 }
05623                 else if (!strcmp(argv[j], "-settings") && (++j < argc)) 
05624                 {
05625                         gSettingsFileName = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, argv[j]);
05626                 }
05627                 else if (!strcmp(argv[j], "-setdefault") && (j + 2 < argc)) 
05628                 {
05629                         std::string control_name;
05630                         std::string control_value;
05631                         
05632                         j++;
05633                         if (argv[j]) control_name = std::string(argv[j]);
05634 
05635                         j++;
05636                         if (argv[j]) control_value = std::string(argv[j]);
05637                         
05638                         
05639                         if (!control_name.empty())
05640                         {
05641                                 gCommandLineSettings[control_name] = control_value;
05642                         }
05643                 }
05644                 else if (!strcmp(argv[j], "-set") && (j + 2 < argc)) 
05645                 {
05646                         std::string control_name;
05647                         std::string control_value;
05648                         
05649                         j++;
05650                         if (argv[j]) control_name = std::string(argv[j]);
05651 
05652                         j++;
05653                         if (argv[j]) control_value = std::string(argv[j]);
05654                         
05655                         
05656                         if (!control_name.empty())
05657                         {
05658                                 gCommandLineForcedSettings[control_name] = control_value;
05659                         }
05660                 }
05661                 else if (!strcmp(argv[j], "-login"))
05662                 {
05663                         if (j + 3 < argc)
05664                         {
05665                                 j++;
05666                                 gCmdLineFirstName = argv[j];
05667                                 j++;
05668                                 gCmdLineLastName = argv[j];
05669                                 j++;
05670                                 gCmdLinePassword = argv[j];
05671                         }
05672                         else
05673                         {
05674                                 
05675                                 llerrs << "Not enough parameters to -login. Did you mean -loginuri?" << llendl;
05676                         }
05677                 }
05678                 else if (!strcmp(argv[j], "-god"))
05679                 {
05680                         gGodConnect = TRUE;
05681                 }
05682                 else if (!strcmp(argv[j], "-noconsole"))
05683                 {
05684                         gUseConsole = FALSE;
05685                 }
05686                 else if (!strcmp(argv[j], "-safe"))
05687                 {
05688                         llinfos << "Setting viewer feature table to run in safe mode, resetting prefs" << llendl;
05689                         gFeatureManagerp->setSafe(TRUE);
05690                 }
05691                 else if (!strcmp(argv[j], "-multiple"))
05692                 {
05693                         gMultipleViewersOK = TRUE;
05694                 }
05695                 else if (!strcmp(argv[j], "-nomultiple"))
05696                 {
05697                         gMultipleViewersOK = FALSE;
05698                 }
05699                 else if (!strcmp(argv[j], "-novoice"))
05700                 {
05701                         gDisableVoice = TRUE;
05702                 }
05703                 else if (!strcmp(argv[j], "-nothread"))
05704                 {
05705                         LLVFile::ALLOW_ASYNC = FALSE;
05706                         llinfos << "Running VFS in nothread mode" << llendl;
05707                 }
05708                 
05709                 
05710                 else if (LLURLDispatcher::isSLURL(argv[j])
05711                                  || !strcmp(argv[j], "-url") && (++j < argc)) 
05712                 {
05713                         std::string slurl = argv[j];
05714                         if (LLURLDispatcher::isSLURLCommand(slurl))
05715                         {
05716                                 LLStartUp::sSLURLCommand = slurl;
05717                         }
05718                         else
05719                         {
05720                                 LLURLSimString::setString(slurl);
05721                         }
05722                         
05723                         
05724                         
05725                         
05726                         gArgs += argv[j];
05727                         return 0;
05728                 }
05729                 else if (!strcmp(argv[j], "-ignorepixeldepth"))
05730                 {
05731                         gIgnorePixelDepth = TRUE;
05732                 }
05733                 else if (!strcmp(argv[j], "-cooperative"))
05734                 {
05735                         S32 ms_to_yield = 0;
05736                         if(++j < argc)
05737                         {
05738                                 S32 rv = sscanf(argv[j], "%d", &ms_to_yield);
05739                                 if(0 == rv)
05740                                 {
05741                                         --j;
05742                                 }
05743                         }
05744                         else
05745                         {
05746                                 --j;
05747                         }
05748                         gYieldMS = ms_to_yield;
05749                         gYieldTime = TRUE;
05750                 }
05751                 else if (!strncmp(argv[j], "-lang", 5))
05752                 {
05753                         j++;
05754                         if (argv[j])
05755                                 gSavedSettings.setString("Language", std::string(argv[j]));
05756                 }
05757                 else if (!strcmp(argv[j], "-no-verify-ssl-cert"))
05758                 {
05759                         gVerifySSLCert = false;
05760                 }
05761                 else if ( (!strcmp(argv[j], "--channel") || !strcmp(argv[j], "-channel"))  && (++j < argc)) 
05762                 {
05763                         gChannelName = argv[j];
05764                 }
05765 #if LL_DARWIN
05766                 else if (!strncmp(argv[j], "-psn_", 5))
05767                 {
05768                         
05769                         
05770                 }
05771 #endif
05772                 else
05773                 {
05774 
05775                         
05776                         
05777                         llwarns << "Possible unknown keyword " << argv[j] << llendl;
05778 
05779                         
05780                         llinfos << USAGE << llendl;
05781                         
05782                 }
05783         }
05784         return 0;
05785 }
05786 
05787 
05788 
05789 void load_name_cache()
05790 {
05791         if (!gCacheName) return;
05792 
05793         std::string name_cache;
05794         name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
05795         FILE* name_cache_fp = LLFile::fopen(name_cache.c_str(), "r");           
05796         if (name_cache_fp)
05797         {
05798                 gCacheName->importFile(name_cache_fp);
05799                 fclose(name_cache_fp);
05800         }
05801 }
05802 
05803 void save_name_cache()
05804 {
05805         if (!gCacheName) return;
05806 
05807         std::string name_cache;
05808         name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
05809         FILE* name_cache_fp = LLFile::fopen(name_cache.c_str(), "w");           
05810         if (name_cache_fp)
05811         {
05812                 gCacheName->exportFile(name_cache_fp);
05813                 fclose(name_cache_fp);
05814         }
05815 }
05816 
05817 void load_region_name_cache()
05818 {
05819         if (!gCacheName) return;
05820 
05821         
05822         gRegionNameCache->importFile(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "region_names.xml"), true);
05823         gRegionNameCache->importFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "region_names.xml"), false);
05824 }
05825 
05826 void save_region_name_cache()
05827 {
05828         if (!gCacheName) return;
05829 
05830         std::string name_cache;
05831         name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "region_names.xml");
05832         gRegionNameCache->exportFile(name_cache);
05833 }
05834 
05835 
05836 void login_alert_done(S32 option, void* user_data)
05837 {
05838         LLPanelLogin::giveFocus();
05839 }
05840 
05841 void disconnect_viewer(void *)
05842 {
05843         if (gDisconnected)
05844         {
05845                 return;
05846         }
05847         
05848         
05849         
05850         
05851 
05852         llinfos << "Disconnecting viewer!" << llendl;
05853 
05854         
05855         gFrameStats.dump();
05856 
05857 
05858         
05859 #if !LL_WINDOWS
05860         release_signals();
05861 #endif
05862 
05863         
05864         gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
05865 
05866         
05867         if (!gNoRender)
05868         {
05869                 if (gFloaterView)
05870                 {
05871                         gFloaterView->restoreAll();
05872                 }
05873         }
05874 
05875         if (gSelectMgr)
05876         {
05877                 gSelectMgr->deselectAll();
05878         }
05879 
05880         if (!gNoRender)
05881         {
05882                 
05883                 gInventory.cache(gAgent.getInventoryRootID(), gAgent.getID());
05884                 if(gInventoryLibraryRoot.notNull() && gInventoryLibraryOwner.notNull())
05885                 {
05886                         gInventory.cache(gInventoryLibraryRoot, gInventoryLibraryOwner);
05887                 }
05888         }
05889 
05890         save_name_cache();
05891         save_region_name_cache();
05892 
05893         
05894         LLInventoryView::cleanup();
05895 
05896         
05897         user_logout();
05898 
05899         
05900 
05901         
05902         gAgent.cleanup();
05903 
05904         gObjectList.destroy();
05905         delete gWorldp;
05906         gWorldp = NULL;
05907 
05908         cleanup_xfer_manager();
05909         gDisconnected = TRUE;
05910 }
05911 
05912 
05913 void remove_cache_files(const char* file_mask)
05914 {
05915         char mask[LL_MAX_PATH];         
05916         snprintf(mask, LL_MAX_PATH, "%s%s", gDirUtilp->getDirDelimiter().c_str(), file_mask);           
05917         gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "").c_str(), mask);
05918 }
05919 
05920 
05921 
05922 
05923 void finish_early_exit(S32 option, void* userdata)
05924 {
05925         app_force_quit(NULL);
05926 }
05927 
05928 void app_early_exit(const LLString& mesg)
05929 {
05930         llwarns << "app_early_exit: " << mesg << llendl;
05931         gDoDisconnect = TRUE;
05932 
05933 
05934 
05935         LLAlertDialog::showCritical(mesg, finish_early_exit, NULL);
05936 }
05937 
05938 
05939 void app_force_exit(S32 arg)
05940 {
05941         remove_marker_file();
05942         exit(arg);
05943 }
05944 
05945 
05946 void finish_disconnect(S32 option, void* userdata)
05947 {
05948         if (1 == option)
05949         {
05950                 app_force_quit(NULL);
05951         }
05952 }
05953 
05954 
05955 void finish_forced_disconnect(S32 , void* )
05956 {
05957         app_force_quit(NULL);
05958 }
05959 
05960 void send_logout_request()
05961 {
05962         if(!gLogoutRequestSent)
05963         {
05964                 LLMessageSystem* msg = gMessageSystem;
05965                 msg->newMessageFast(_PREHASH_LogoutRequest);
05966                 msg->nextBlockFast(_PREHASH_AgentData);
05967                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
05968                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
05969                 gAgent.sendReliableMessage();
05970 
05971                 gLogoutTimer.reset();
05972                 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
05973                 gLogoutRequestSent = TRUE;
05974                 
05975                 gVoiceClient->leaveChannel();
05976         }
05977 }
05978 
05979 void do_disconnect(const LLString& mesg)
05980 {
05981         if (gDoDisconnect)
05982     {
05983                 
05984                 
05985                 return;
05986     }
05987 
05988         
05989         LLString big_reason = LLAgent::sTeleportErrorMessages[mesg];
05990         if ( big_reason.size() == 0 )
05991         {
05992                 big_reason = mesg;
05993         }
05994 
05995         LLStringBase<char>::format_map_t args;
05996         gDoDisconnect = TRUE;
05997 
05998         if (LLStartUp::getStartupState() < STATE_STARTED)
05999         {
06000                 
06001                 args["[ERROR_MESSAGE]"] = big_reason;
06002                 gViewerWindow->alertXml("ErrorMessage", args, finish_forced_disconnect);
06003         }
06004         else
06005         {
06006                 args["[MESSAGE]"] = big_reason;
06007                 gViewerWindow->alertXml("YouHaveBeenLoggedOut", args, finish_disconnect );
06008         }
06009 }
06010 
06011 const LLUUID& agent_get_id()
06012 {
06013         return gAgent.getID();
06014 }
06015 
06016 const LLUUID& agent_get_session_id()
06017 {
06018         return gAgent.getSessionID();
06019 }
06020 
06021 void agent_send_reliable_message()
06022 {
06023         gAgent.sendReliableMessage();
06024 }
06025 
06026 void bad_network_handler()
06027 {
06028         
06029         gMessageSystem->dumpPacketToLog();
06030 
06031         
06032         
06033 
06034         gPurgeOnExit = TRUE;
06035 
06036 #if LL_WINDOWS
06037         LLWinDebug::handleException(NULL);
06038 #else
06039         
06040         if (gCrashCallback)
06041         {
06042                 gCrashCallback();
06043         }
06044 #endif
06045 
06046         std::ostringstream message;
06047         message <<
06048                 "The viewer has detected mangled network data indicative\n"
06049                 "of a bad upstream network connection or an incomplete\n"
06050                 "local installation of " << gSecondLife << ". \n"
06051                 " \n"
06052                 "Try uninstalling and reinstalling to see if this resolves \n"
06053                 "the issue. \n"
06054                 " \n"
06055                 "If the problem continues, see the Tech Support FAQ at: \n"
06056                 "www.secondlife.com/support";
06057         do_disconnect(message.str());
06058 }
06059 
06060 
06061 
06062 void save_avatar(void*)
06063 {
06064         LLFloaterSaveAvatar::show();
06065 }
06066 
06067 void cleanup_app()
06068 {
06069         
06070         
06071         LLMortician::setZealous(TRUE);
06072 
06073         LLVoiceClient::terminate();
06074         
06075         disconnect_viewer(NULL);
06076 
06077         llinfos << "Viewer disconnected" << llendflush;
06078 
06079         gDisconnectedImagep = NULL;
06080         release_start_screen(); 
06081 
06082         LLError::logToFixedBuffer(NULL);
06083 
06084         llinfos << "Cleaning Up" << llendflush;
06085 
06086         LLKeyframeDataCache::clear();
06087         
06088         
06089         LLHUDObject::cleanupHUDObjects();
06090         llinfos << "HUD Objects cleaned up" << llendflush;
06091 
06092         
06093 #if 0 // this seems to get us stuck in an infinite loop...
06094         gTransferManager.cleanup();
06095 #endif
06096         
06097         
06098         delete gWorldMap;
06099         gWorldMap = NULL;
06100 
06101         delete gHUDManager;
06102         gHUDManager = NULL;
06103 
06104         delete gToolMgr;
06105         gToolMgr = NULL;
06106 
06107         delete gAssetStorage;
06108         gAssetStorage = NULL;
06109 
06110         LLPolyMesh::freeAllMeshes();
06111 
06112         delete gCacheName;
06113         gCacheName = NULL;
06114 
06115         delete gGlobalEconomy;
06116         gGlobalEconomy = NULL;
06117 
06118         delete gLocalSpeakerMgr;
06119         gLocalSpeakerMgr = NULL;
06120 
06121         LLNotifyBox::cleanup();
06122 
06123         llinfos << "Global stuff deleted" << llendflush;
06124 
06125 #if !LL_RELEASE_FOR_DOWNLOAD
06126         if (gAudiop)
06127         {
06128                 gAudiop->shutdown();
06129         }
06130 #else
06131         
06132         
06133         llwarns << "Hack, skipping audio engine cleanup" << llendflush;
06134 #endif
06135 
06136 
06137         
06138         
06139 
06140         LLMediaEngine::cleanupClass();
06141         
06142 #if LL_QUICKTIME_ENABLED
06143         if (gQuickTimeInitialized)
06144         {
06145                 
06146                 llinfos << "Cleaning up QuickTime" << llendl;
06147                 ExitMovies ();
06148                 #if LL_WINDOWS
06149                         
06150                         TerminateQTML ();
06151                 #endif
06152         }
06153         llinfos << "Quicktime cleaned up" << llendflush;
06154 #endif
06155 
06156 #if LL_GSTREAMER_ENABLED
06157         llinfos << "Cleaning up GStreamer" << llendl;
06158         UnloadGStreamer();
06159         llinfos << "GStreamer cleaned up" << llendflush;        
06160 #endif
06161 
06162         llinfos << "Cleaning up feature manager" << llendflush;
06163         delete gFeatureManagerp;
06164         gFeatureManagerp = NULL;
06165 
06166         
06167         
06168         
06169         
06170         cleanup_saved_settings();
06171         llinfos << "Settings patched up" << llendflush;
06172 
06173         delete gAudiop;
06174         gAudiop = NULL;
06175 
06176         
06177         remove_cache_files("*.wav");
06178         remove_cache_files("*.tmp");
06179         remove_cache_files("*.lso");
06180         remove_cache_files("*.out");
06181         remove_cache_files("*.dsf");
06182         remove_cache_files("*.bodypart");
06183         remove_cache_files("*.clothing");
06184 
06185         llinfos << "Cache files removed" << llendflush;
06186 
06187 
06188         cleanup_menus();
06189 
06190         
06191         while (1)
06192         {
06193                 S32 pending = LLVFSThread::updateClass(0);
06194                 pending += LLLFSThread::updateClass(0);
06195                 if (!pending)
06196                 {
06197                         break;
06198                 }
06199                 llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
06200                 ms_sleep(100);
06201         }
06202         llinfos << "Shutting down." << llendflush;
06203         
06204         
06205         
06206         
06207         delete gViewerWindow;
06208         gViewerWindow = NULL;
06209         llinfos << "ViewerWindow deleted" << llendflush;
06210 
06211         
06212         delete gKeyboard;
06213         gKeyboard = NULL;
06214 
06215         
06216         
06217         LLSelectMgr::cleanupGlobals();
06218 
06219         LLViewerObject::cleanupVOClasses();
06220                 
06221         LLTracker::cleanupInstance();
06222         
06223 #if LL_LIBXUL_ENABLED
06224         
06225         
06226         LLMozLib::getInstance()->reset();
06227 #endif
06228 
06229 #if LL_WINDOWS
06230         gDXHardware.cleanup();
06231 #endif // LL_WINDOWS
06232 
06233 #if LL_WINDOWS && LL_LCD_COMPILE
06234         
06235         delete gLcdScreen;
06236 #endif
06237 
06238         if (!gVolumeMgr->cleanup())
06239         {
06240                 llwarns << "Remaining references in the volume manager!" << llendflush;
06241         }
06242 
06243         LLViewerParcelMgr::cleanupGlobals();
06244 
06245         delete gViewerStats;
06246         gViewerStats = NULL;
06247 
06248         end_messaging_system();
06249 
06250         LLFollowCamMgr::cleanupClass();
06251         LLVolumeMgr::cleanupClass();
06252         LLWorldMapView::cleanupClass();
06253         LLUI::cleanupClass();
06254         
06255         
06256         
06257         
06258         
06259         
06260         LLVFile::cleanupClass();
06261         llinfos << "VFS cleaned up" << llendflush;
06262 
06263         
06264         gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
06265 
06266         
06267         
06268         gSavedSettings.saveToFile(gSettingsFileName, TRUE);
06269         if (!gPerAccountSettingsFileName.empty())
06270         {
06271                 gSavedPerAccountSettings.saveToFile(gPerAccountSettingsFileName, TRUE);
06272         }
06273         llinfos << "Saved settings" << llendflush;
06274 
06275         std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
06276         
06277         gCrashSettings.saveToFile(crash_settings_filename.c_str(), FALSE);
06278 
06279         delete gUICtrlFactory;
06280         gUICtrlFactory = NULL;
06281 
06282         gSavedSettings.cleanup();
06283         gViewerArt.cleanup();
06284         gColors.cleanup();
06285         gCrashSettings.cleanup();
06286 
06287         if (gMuteListp)
06288         {
06289                 
06290                 gMuteListp->cache(gAgent.getID());
06291 
06292                 delete gMuteListp;
06293                 gMuteListp = NULL;
06294         }
06295 
06296         if (gPurgeOnExit)
06297         {
06298                 llinfos << "Purging all cache files on exit" << llendflush;
06299                 char mask[LL_MAX_PATH];         
06300                 snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str());             
06301                 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
06302         }
06303 
06304         remove_marker_file(); 
06305         
06306         close_debug();
06307 
06308         
06309         LLTimer idleTimer;
06310         idleTimer.reset();
06311         const F64 max_idle_time = 5.f; 
06312         while(1)
06313         {
06314                 S32 pending = 0;
06315                 pending += gTextureCache->update(1); 
06316                 pending += gImageDecodeThread->update(1); 
06317                 pending += gTextureFetch->update(1); 
06318                 pending += LLVFSThread::updateClass(0);
06319                 pending += LLLFSThread::updateClass(0);
06320                 F64 idle_time = idleTimer.getElapsedTimeF64();
06321                 if (!pending || idle_time >= max_idle_time)
06322                 {
06323                         llwarns << "Quitting with pending background tasks." << llendl;
06324                         break;
06325                 }
06326         }
06327         
06328         
06329         
06330         gTextureCache->shutdown();
06331         gTextureFetch->shutdown();
06332         gImageDecodeThread->shutdown();
06333         delete gTextureCache;
06334         delete gTextureFetch;
06335         delete gImageDecodeThread;
06336 
06337         gImageList.shutdown(); 
06338         
06339         
06340         LLImageJ2C::closeDSO();
06341         LLImageFormatted::cleanupClass();
06342         LLVFSThread::cleanupClass();
06343         LLLFSThread::cleanupClass();
06344 
06345         llinfos << "VFS Thread finished" << llendflush;
06346 
06347 #ifndef LL_RELEASE_FOR_DOWNLOAD
06348         llinfos << "Auditing VFS" << llendl;
06349         gVFS->audit();
06350 #endif
06351 
06352         
06353         
06354         delete gStaticVFS;
06355         gStaticVFS = NULL;
06356         delete gVFS;
06357         gVFS = NULL;
06358         
06359         LLCurl::cleanup();
06360 
06361         
06362         LLCommon::cleanupClass();
06363 
06364         end_messaging_system();
06365 }
06366 
06367 
06368 void resetURIs()
06369 {
06370         gLoginURIs.clear();
06371         gHelperURI.clear();
06372 }
06373 
06374 const std::vector<std::string>& getLoginURIs()
06375 {
06376         if (gLoginURIs.empty())
06377         {
06378                 
06379                 gLoginURIs = LLSRV::rewriteURI(gUserServerDomainName[gUserServerChoice].mLoginURI);
06380         }
06381         return gLoginURIs;
06382 }
06383 
06384 const std::string& getHelperURI()
06385 {
06386         if (gHelperURI.empty())
06387         {
06388                 
06389                 gHelperURI = gUserServerDomainName[gUserServerChoice].mHelperURI;
06390         }
06391         return gHelperURI;
06392 }
06393 
06394 void errorCallback(const std::string &error_string)
06395 {
06396 #ifndef LL_RELEASE_FOR_DOWNLOAD
06397         OSMessageBox(error_string.c_str(), "Fatal Error", OSMB_OK);
06398 #endif
06399         LLError::crashAndLoop(error_string);
06400 }
06401 
06402