Newer
Older
Xiaohong Bao
committed
}
else if(idle_time >= max_idle_time)
Steven Bennetts
committed
{
LL_WARNS() << "Quitting with pending background tasks." << LL_ENDL;
Steven Bennetts
committed
break;
}
}
Xiaohong Bao
committed
if (mPurgeUserDataOnExit)
{
// Ideally we should not save anything from this session since it is going to be purged now,
// but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code
std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId();
gDirUtilp->deleteDirAndContents(user_path);
}
Steven Bennetts
committed
// Delete workers first
// shotdown all worker threads before deleting them in case of co-dependencies
Monty Brandenberg
committed
mAppCoreHttp.requestStop();
Steven Bennetts
committed
sTextureFetch->shutdown();
sTextureCache->shutdown();
Steven Bennetts
committed
sImageDecodeThread->shutdown();
Xiaohong Bao
committed
sTextureFetch->shutDownTextureCacheThread() ;
sTextureFetch->shutDownImageDecodeThread() ;
LL_INFOS() << "Shutting down message system" << LL_ENDL;
end_messaging_system();
// Non-LLCurl libcurl library
mAppCoreHttp.cleanup();
SUBSYSTEM_CLEANUP(LLFilePickerThread);
maxim_productengine
committed
SUBSYSTEM_CLEANUP(LLDirPickerThread);
//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
Steven Bennetts
committed
delete sTextureCache;
sTextureCache = NULL;
delete sTextureFetch;
sTextureFetch = NULL;
delete sImageDecodeThread;
sImageDecodeThread = NULL;
delete mFastTimerLogThread;
mFastTimerLogThread = NULL;
if (LLFastTimerView::sAnalyzePerformance)
{
LL_INFOS() << "Analyzing performance" << LL_ENDL;
Richard Linden
committed
std::string baseline_name = LLTrace::BlockTimer::sLogName + "_baseline.slp";
std::string current_name = LLTrace::BlockTimer::sLogName + ".slp";
Richard Linden
committed
std::string report_name = LLTrace::BlockTimer::sLogName + "_report.csv";
Merov Linden
committed
LLFastTimerView::doAnalysis(
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ;
LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL;
Steve Bennetts
committed
//SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown()
//because some new image might be generated during cleaning up media. --bao
gTextureList.shutdown(); // shutdown again in case a callback added something
Steven Bennetts
committed
// This should eventually be done in LLAppViewer
SUBSYSTEM_CLEANUP(LLVFSThread);
SUBSYSTEM_CLEANUP(LLLFSThread);
Steven Bennetts
committed
#ifndef LL_RELEASE_FOR_DOWNLOAD
Mark Palange (Mani)
committed
if(gVFS)
{
gVFS->audit();
}
Steven Bennetts
committed
#endif
Steven Bennetts
committed
// For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
// (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
delete gStaticVFS;
gStaticVFS = NULL;
delete gVFS;
gVFS = NULL;
Steven Bennetts
committed
gSavedSettings.cleanup();
LLUIColorTable::instance().clear();
LLWatchdog::getInstance()->cleanup();
// If we're exiting to launch an URL, do that here so the screen
Steven Bennetts
committed
// is at the right resolution before we launch IE.
if (!gLaunchFileOnQuit.empty())
{
LL_INFOS() << "Launch file on quit." << LL_ENDL;
Steven Bennetts
committed
#if LL_WINDOWS
// Indicate an application is starting.
SetCursor(LoadCursor(NULL, IDC_WAIT));
#endif
// HACK: Attempt to wait until the screen res. switch is complete.
ms_sleep(1000);
LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
LL_INFOS() << "File launched." << LL_ENDL;
Steven Bennetts
committed
}
LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
SUBSYSTEM_CLEANUP(LLProxy);
LLCore::LLHttp::cleanup();
Steven Bennetts
committed
Andrew A. de Laix
committed
LLMainLoopRepeater::instance().stop();
ll_close_fail_log();
LLError::LLCallStacks::cleanup();
// It's not at first obvious where, in this long sequence, a generic cleanup
// call OUGHT to go. So let's say this: as we migrate cleanup from
// explicit hand-placed calls into the generic mechanism, eventually
// all cleanup will get subsumed into the generic call. So the calls you
// still see above are calls that MUST happen before the generic cleanup
// kicks in.
// This calls every remaining LLSingleton's cleanupSingleton() and
// deleteSingleton() methods.
LLSingletonBase::deleteAll();
LL_INFOS() << "Goodbye!" << LL_ENDL;
removeDumpDir();
Steven Bennetts
committed
// return 0;
return true;
}
// A callback for LL_ERRS() to call during the watchdog error.
void watchdog_llerrs_callback(const std::string &error_string)
{
gLLErrorActivated = true;
gDebugInfo["FatalMessage"] = error_string;
LLAppViewer::instance()->writeDebugInfo();
#ifdef LL_WINDOWS
RaiseException(0,0,0,0);
#else
raise(SIGQUIT);
#endif
}
// A callback for the watchdog to call.
void watchdog_killer_callback()
{
LLError::setFatalFunction(watchdog_llerrs_callback);
LL_ERRS() << "Watchdog killer event" << LL_ENDL;
Steven Bennetts
committed
bool LLAppViewer::initThreads()
{
static const bool enable_threads = true;
LLImage::initParamSingleton(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
Xiaohong Bao
committed
LLVFSThread::initClass(enable_threads && false);
LLLFSThread::initClass(enable_threads && false);
Steven Bennetts
committed
// Image decoding
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
Steven Bennetts
committed
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
sImageDecodeThread,
enable_threads && true,
app_metrics_qa_mode);
Steven Bennetts
committed
Richard Linden
committed
if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog)
LLTrace::BlockTimer::setLogLock(new LLMutex());
Richard Linden
committed
mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName);
mFastTimerLogThread->start();
}
// Mesh streaming and caching
gMeshRepo.init();
maxim_productengine
committed
LLDirPickerThread::initClass();
Steven Bennetts
committed
// *FIX: no error handling here!
return true;
}
void errorCallback(const std::string& error_string)
Steven Bennetts
committed
{
static std::string last_message;
if (last_message != error_string)
{
#ifdef SHOW_ASSERT
U32 response = OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_YESNO);
if (response == OSBTN_NO)
{
last_message = error_string;
return;
}
Steven Bennetts
committed
#endif
//Set the ErrorActivated global so we know to create a marker file
gLLErrorActivated = true;
gDebugInfo["FatalMessage"] = error_string;
// We're not already crashing -- we simply *intend* to crash. Since we
// haven't actually trashed anything yet, we can afford to write the whole
// static info file.
LLAppViewer::instance()->writeDebugInfo();
// [SL:KB] - Patch: Viewer-Build | Checked: Catznip-2.4
Kitty Barnett
committed
#if !LL_RELEASE_FOR_DOWNLOAD && LL_WINDOWS
Kitty Barnett
committed
#else
LLError::crashAndLoop(error_string);
Kitty Barnett
committed
#endif // LL_RELEASE_WITH_DEBUG_INFO && LL_WINDOWS
// [/SL:KB]
//#ifndef SHADER_CRASH_NONFATAL
// LLError::crashAndLoop(error_string);
//#endif
}
Steven Bennetts
committed
}
Oz Linden
committed
void LLAppViewer::initLoggingAndGetLastDuration()
Steven Bennetts
committed
{
//
// Set up logging defaults for the viewer
//
LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
);
Steven Bennetts
committed
LLError::setFatalFunction(errorCallback);
Richard Linden
committed
//LLError::setTimeFunction(getRuntime);
Steven Bennetts
committed
// Remove the last ".old" log file.
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
LLFile::remove(old_log_file);
Steven Bennetts
committed
Steven Bennetts
committed
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
/*
* Before touching any log files, compute the duration of the last run
* by comparing the ctime of the previous start marker file with the ctime
* of the last log file.
*/
std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME);
llstat start_marker_stat;
llstat log_file_stat;
Oz Linden
committed
std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below
int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat);
int log_stat_result = LLFile::stat(log_file, &log_file_stat);
if ( 0 == start_stat_result && 0 == log_stat_result )
{
int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime;
// only report a last run time if the last viewer was the same version
// because this stat will be counted against this version
Oz Linden
committed
if ( markerIsSameVersion(start_marker_file_name) )
{
gLastExecDuration = elapsed_seconds;
}
else
{
duration_log_stream << "start marker from some other version; duration is not reported";
gLastExecDuration = -1;
}
}
else
{
// at least one of the LLFile::stat calls failed, so we can't compute the run time
Oz Linden
committed
duration_log_stream << "duration stat failure; start: "<< start_stat_result << " log: " << log_stat_result;
gLastExecDuration = -1; // unknown
}
Oz Linden
committed
std::string duration_log_msg(duration_log_stream.str());
// Create a new start marker file for comparison with log file time for the next run
LLAPRFile start_marker_file ;
Oz Linden
committed
start_marker_file.open(start_marker_file_name, LL_APR_WB);
if (start_marker_file.getFileHandle())
{
recordMarkerVersion(start_marker_file);
start_marker_file.close();
}
// Rename current log file to ".old"
LLFile::rename(log_file, old_log_file);
Steven Bennetts
committed
// Set the log file to SecondLife.log
LLError::logToFile(log_file);
Oz Linden
committed
if (!duration_log_msg.empty())
{
LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
}
Steven Bennetts
committed
}
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
bool set_defaults)
LL_ERRS() << "Invalid settings location list" << LL_ENDL;
for (const SettingsGroup& group : mSettingsLocationList->groups)
if (group.name() != location_key) continue;
ELLPath path_index = (ELLPath)group.path_index();
if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
LL_ERRS() << "Out of range path index in app_settings/settings_files.xml" << LL_ENDL;
for (const SettingsFile& file : group.files)
LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name()
<< " - from location " << location_key << LL_ENDL;
LLControlGroup* settings_group = LLControlGroup::getInstance(file.name);
LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL;
if (file.file_name_setting.isProvided()
&& gSavedSettings.controlExists(file.file_name_setting.getValue()))
full_settings_path = gSavedSettings.getString(file.file_name_setting.getValue());
Aaron Stone
committed
if (full_settings_path.empty())
{
continue;
}
else if (!gDirUtilp->fileExists(full_settings_path))
{
// search in default path
full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
}
full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name());
if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent))
LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL;
LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL;
return false;
}
else
{
// only complain if we actually have a filename at this point
if (!full_settings_path.empty())
{
LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL;
std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
const std::string& file)
for (const SettingsGroup& group : mSettingsLocationList->groups)
if (group.name() == location_key)
for (const SettingsFile& settings_file : group.files)
if (settings_file.name() == file)
return settings_file.file_name;
void LLAppViewer::loadColorSettings()
{
LLUIColorTable::instance().loadFromSettings();
namespace
{
void handleCommandLineError(LLControlGroupCLP& clp)
{
LL_WARNS() << "Error parsing command line options. Command Line options ignored." << LL_ENDL;
LL_INFOS() << "Command line usage:\n" << clp << LL_ENDL;
OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()),
LLStringUtil::null,
OSMB_OK);
}
} // anonymous namespace
Steven Bennetts
committed
bool LLAppViewer::initConfiguration()
//Load settings files list
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
if (!success)
{
LL_ERRS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL;
}
mSettingsLocationList = new SettingsFiles();
LLXUIParser parser;
parser.readXUI(root, *mSettingsLocationList, settings_file_list);
if (!mSettingsLocationList->validateBlock())
{
LL_ERRS() << "Invalid settings file list " << settings_file_list << LL_ENDL;
// The settings and command line parsing have a fragile
// order-of-operation:
// - load defaults from app_settings
// - set procedural settings values
// - read command line settings
// - selectively apply settings needed to load user settings.
// - load overrides from user_settings
// - apply command line settings (to override the overrides)
// - load per account settings (happens in llstartup
bool set_defaults = true;
if(!loadSettingsFromDirectory("Default", set_defaults))
OSMessageBox(
"Unable to load default settings file. The installation may be corrupted.",
LLStringUtil::null,OSMB_OK);
initStrings(); // setup paths for LLTrans based on settings files only
// - set procedural settings
// Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
gSavedSettings.setString("ClientSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
#ifndef LL_RELEASE_FOR_DOWNLOAD
// provide developer build only overrides for these control variables that are not
// persisted to settings.xml
LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow");
if (c)
{
c->setValue(true, false);
}
c = gSavedSettings.getControl("AllowMultipleViewers");
if (c)
{
c->setValue(true, false);
}
Andrew A. de Laix
committed
gSavedSettings.setS32("WatchdogEnabled", 0);
// These are warnings that appear on the first experience of that condition.
// They are already set in the settings_default.xml file, but still need to be added to LLFirstUse
// for disable/reset ability
// LLFirstUse::addConfigVariable("FirstBalanceIncrease");
// LLFirstUse::addConfigVariable("FirstBalanceDecrease");
// LLFirstUse::addConfigVariable("FirstSit");
// LLFirstUse::addConfigVariable("FirstMap");
// LLFirstUse::addConfigVariable("FirstGoTo");
// LLFirstUse::addConfigVariable("FirstBuild");
James Cook
committed
// LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
// LLFirstUse::addConfigVariable("FirstTeleport");
// LLFirstUse::addConfigVariable("FirstOverrideKeys");
// LLFirstUse::addConfigVariable("FirstAttach");
// LLFirstUse::addConfigVariable("FirstAppearance");
// LLFirstUse::addConfigVariable("FirstInventory");
// LLFirstUse::addConfigVariable("FirstSandbox");
// LLFirstUse::addConfigVariable("FirstFlexible");
// LLFirstUse::addConfigVariable("FirstDebugMenus");
// LLFirstUse::addConfigVariable("FirstSculptedPrim");
// LLFirstUse::addConfigVariable("FirstVoice");
// LLFirstUse::addConfigVariable("FirstMedia");
LLControlGroupCLP clp;
std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
"cmd_line.xml");
clp.configure(cmd_line_config, &gSavedSettings);
if(!initParseCommandLine(clp))
{
handleCommandLineError(clp);
// - selectively apply settings
// If the user has specified a alternate settings file name.
// Load it now before loading the user_settings/settings.xml
if(clp.hasOption("settings"))
{
std::string user_settings_filename =
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
clp.getOption("settings")[0]);
gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
LL_INFOS("Settings") << "Using command line specified settings filename: "
<< user_settings_filename << LL_ENDL;
// - load overrides from user_settings
loadSettingsFromDirectory("User");
if (gSavedSettings.getBOOL("FirstRunThisInstall"))
{
// Set firstrun flag to indicate that some further init actiona should be taken
pavelkproductengine
committed
// like determining screen DPI value and so on
mIsFirstRun = true;
Richard Linden
committed
gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
std::string session_settings_filename = clp.getOption("sessionsettings")[0];
gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
LL_INFOS("Settings") << "Using session settings filename: "
<< session_settings_filename << LL_ENDL;
}
loadSettingsFromDirectory("Session");
if (clp.hasOption("usersessionsettings"))
{
std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];
gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
LL_INFOS("Settings") << "Using user session settings filename: "
<< user_session_settings_filename << LL_ENDL;
// - apply command line settings
if (! clp.notify())
{
handleCommandLineError(clp);
return false;
}
Vadim ProductEngine
committed
// Register the core crash option as soon as we can
// if we want gdb post-mortem on cores we need to be up and running
// ASAP or we might miss init issue etc.
if(gSavedSettings.getBOOL("DisableCrashLogger"))
Vadim ProductEngine
committed
{
LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << LL_ENDL;
disableCrashlogger();
Vadim ProductEngine
committed
}
// Start up the debugging console before handling other options.
if (gSavedSettings.getBOOL("ShowConsoleWindow"))
{
initConsole();
}
if(clp.hasOption("help"))
{
msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp;
msg.str(),
Mark Palange
committed
LLStringUtil::null,
return false;
}
if(clp.hasOption("set"))
{
const LLCommandLineParser::token_vector_t& set_values = clp.getOption("set");
if(0x1 & set_values.size())
{
LL_WARNS() << "Invalid '--set' parameter count." << LL_ENDL;
}
else
{
LLCommandLineParser::token_vector_t::const_iterator itr = set_values.begin();
for(; itr != set_values.end(); ++itr)
{
const std::string& name = *itr;
const std::string& value = *(++itr);
Aaron Stone
committed
std::string name_part;
std::string group_part;
LLControlVariable* control = NULL;
// Name can be further split into ControlGroup.Name, with the default control group being Global
size_t pos = name.find('.');
if (pos != std::string::npos)
{
group_part = name.substr(0, pos);
name_part = name.substr(pos+1);
LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL;
Aaron Stone
committed
LLControlGroup* g = LLControlGroup::getInstance(group_part);
if (g) control = g->getControl(name_part);
}
else
{
LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL;
Aaron Stone
committed
control = gSavedSettings.getControl(name);
}
if (control)
Aaron Stone
committed
control->setValue(value, false);
LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL;
}
}
}
}
#if AL_VIEWER_EVENT_RECORDER
if (clp.hasOption("logevents")) {
LLViewerEventRecorder::instance().setEventLoggingOn();
#endif
std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
if(! CmdLineChannel.empty())
Mark Palange (Mani)
committed
{
LLVersionInfo::instance().resetChannel(CmdLineChannel);
Mark Palange (Mani)
committed
}
// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup");
if (gSavedSettings.getBOOL("LogPerformance"))
Richard Linden
committed
LLTrace::BlockTimer::sLog = true;
LLTrace::BlockTimer::sLogName = std::string("performance");
std::string test_name(gSavedSettings.getString("LogMetrics"));
if (! test_name.empty())
// '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test
// In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...)
LL_INFOS() << "'--logmetrics' argument : " << test_name << LL_ENDL;
Richard Linden
committed
LLTrace::BlockTimer::sLogName = test_name;
if (clp.hasOption("graphicslevel"))
{
// User explicitly requested --graphicslevel on the command line. We
// expect this switch has already set RenderQualityPerformance. Check
// that value for validity.
U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance");
if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel))
// graphicslevel is valid: save it and engage it later. Capture
// the requested value separately from the settings variable
// because, if this is the first run, LLViewerWindow's constructor
// will call LLFeatureManager::applyRecommendedSettings(), which
// overwrites this settings variable!
mForceGraphicsLevel = graphicslevel;
}
}
LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance");
gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession"));
if (gSavedSettings.getBOOL("DebugSession"))
{
gDebugSession = TRUE;
gDebugGL = TRUE;
ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
}
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
{
// Examining "Language" may not suffice -- see LLUI::getLanguage()
// logic. Unfortunately LLUI::getLanguage() doesn't yet do us much
// good because we haven't yet called LLUI::initClass().
gDirUtilp->setSkinFolder(skinfolder->getValue().asString(),
gSavedSettings.getString("Language"));
}
if (gSavedSettings.getBOOL("SpellCheck"))
{
std::list<std::string> dict_list;
std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary");
boost::split(dict_list, dict_setting, boost::is_any_of(std::string(",")));
if (!dict_list.empty())
{
LLSpellChecker::setUseSpellCheck(dict_list.front());
dict_list.pop_front();
LLSpellChecker::instance().setSecondaryDictionaries(dict_list);
}
}
// Handle slurl use. NOTE: Don't let SL-55321 reappear.
// This initial-SLURL logic, up through the call to
// sendURLToOtherInstance(), must precede LLSplashScreen::show() --
// because if sendURLToOtherInstance() succeeds, we take a fast exit,
// SKIPPING the splash screen and everything else.
// *FIX: This init code should be made more robust to prevent
// the issue SL-55321 from returning. One thought is to allow
// only select options to be set from command line when a slurl
// is specified. More work on the settings system is needed to
// achieve this. For now...
// *NOTE:Mani The command line parser parses tokens and is
// setup to bail after parsing the '--url' option or the
// first option specified without a '--option' flag (or
// any other option that uses the 'last_option' setting -
// see LLControlGroupCLP::configure())
// What can happen is that someone can use IE (or potentially
// other browsers) and do the rough equivalent of command
// injection and steal passwords. Phoenix. SL-55321
std::string starting_location;
std::string cmd_line_login_location(gSavedSettings.getString("CmdLineLoginLocation"));
if(! cmd_line_login_location.empty())
starting_location = cmd_line_login_location;
}
else
std::string default_login_location(gSavedSettings.getString("DefaultLoginLocation"));
if (! default_login_location.empty())
{
starting_location = default_login_location;
}
}
if (! starting_location.empty())
LLStartUp::setStartSLURL(start_slurl);
if(start_slurl.getType() == LLSLURL::LOCATION)
{
LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
}
}
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
// NextLoginLocation is set as a side effect of LLStartUp::setStartSLURL()
std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
if ( !nextLoginLocation.empty() )
{
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
}
else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
&& gSavedSettings.getString("CmdLineLoginLocation").empty())
{
// If automatic login from command line with --login switch
// init StartSLURL location.
std::string start_slurl_setting = gSavedSettings.getString("LoginLocation");
LL_DEBUGS("AppInit") << "start slurl setting '" << start_slurl_setting << "'" << LL_ENDL;
LLStartUp::setStartSLURL(LLSLURL(start_slurl_setting));
}
else
{
// the login location will be set by the login panel (see LLPanelLogin)
}
//RN: if we received a URL, hand it off to the existing instance.
// don't call anotherInstanceRunning() when doing URL handoff, as
// it relies on checking a marker file which will not work when running
// out of different directories
(gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
{
if (sendURLToOtherInstance(start_slurl.getSLURLString()))
// successfully handed off URL to existing instance, exit
return false;
}
Steven Bennetts
committed
// Display splash screen. Must be after above check for previous
// crash as this dialog is always frontmost.
std::string splash_msg;
LLStringUtil::format_map_t args;
args["[APP_NAME]"] = LLTrans::getString("SECOND_LIFE");
splash_msg = LLTrans::getString("StartupLoading", args);
Steven Bennetts
committed
LLSplashScreen::show();
LLSplashScreen::update(splash_msg);
Steven Bennetts
committed
Kelly Washington
committed
//LLVolumeMgr::initClass();
LLVolumeMgr* volume_manager = new LLVolumeMgr();
volume_manager->useMutex(); // LLApp and LLMutex magic must be manually enabled
LLPrimitive::setVolumeManager(volume_manager);
Steven Bennetts
committed
// Note: this is where we used to initialize gFeatureManagerp.
Steven Bennetts
committed
gStartTime = totalTime();
//
// Set the name of the window
//
if (LLVersionInfo::instance().getViewerMaturity() != LLVersionInfo::RELEASE_VIEWER)
gWindowTitle = LLVersionInfo::instance().getChannelAndVersion();
}
else
{
gWindowTitle = LLTrans::getString("APP_NAME");
}
gWindowTitle += std::string(" [DEBUG]");
Steven Bennetts
committed
#endif
AndreyL ProductEngine
committed
if (!gArgs.empty())
{
gWindowTitle += std::string(" ") + gArgs;
AndreyL ProductEngine
committed
}
LLStringUtil::truncate(gWindowTitle, 255);
Steven Bennetts
committed
//
// Check for another instance of the app running
// This happens AFTER LLSplashScreen::show(). That may or may not be
// important.
//
if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers"))
Steven Bennetts
committed
{
LLTrans::getString("MBAlreadyRunning"),
LLStringUtil::null,
OSMB_OK);
return false;
}
Steven Bennetts
committed
Steven Bennetts
committed
{
// This is the second instance of SL. Turn off voice support,
// but make sure the setting is *not* persisted.
LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
if(disable_voice)
Steven Bennetts
committed
{
const BOOL DO_NOT_PERSIST = FALSE;
disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
Steven Bennetts
committed
}
Steven Bennetts
committed
gLastRunVersion = gSavedSettings.getString("LastRunVersion");
loadColorSettings();
// Let anyone else who cares know that we've populated our settings
// variables.
for (const auto& key : LLControlGroup::key_snapshot())
{
// For each named instance of LLControlGroup, send an event saying
// we've initialized an LLControlGroup instance by that name.
LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key));
Kitty Barnett
committed
// [RLVa:KB] - Patch: RLVa-2.1.0
if (LLControlVariable* pControl = gSavedSettings.getControl(RlvSettingNames::Main))
Kitty Barnett
committed
{
if ( (pControl->getValue().asBoolean()) && (pControl->hasUnsavedValue()) )
{
pControl->resetToDefault();
pControl->setValue(false);
std::ostringstream msg;
msg << LLTrans::getString("RLVaToggleMessageLogin", LLSD().with("[STATE]", LLTrans::getString("RLVaToggleDisabled")));
OSMessageBox(msg.str(), LLStringUtil::null, OSMB_OK);
}
}
// [/RLVa:KB]
return true; // Config was successful.
Steven Bennetts
committed
}
// The following logic is replicated in initConfiguration() (to be able to get
// some initial strings before we've finished initializing enough to know the
// current language) and also in init() (to initialize for real). Somehow it
// keeps growing, necessitating a method all its own.
void LLAppViewer::initStrings()
{
std::string strings_file = "strings.xml";
std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
{
// initial check to make sure files are there failed
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
LL_ERRS() << "Viewer failed to find localization and UI files. Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
}
LLTransUtil::parseStrings(strings_file, default_trans_args);
LLTransUtil::parseLanguageStrings("language_settings.xml");
// parseStrings() sets up the LLTrans substitution table. Add this one item.
LLTrans::setDefaultArg("[sourceid]", gSavedSettings.getString("sourceid"));
// Now that we've set "[sourceid]", have to go back through
// default_trans_args and reinitialize all those other keys because some
// of them, in turn, reference "[sourceid]".
for (const std::string& key : default_trans_args)
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
{
std::string brackets(key), nobrackets(key);
// Invalid to inspect key[0] if key is empty(). But then, the entire
// body of this loop is pointless if key is empty().
if (key.empty())
continue;
if (key[0] != '[')
{
// key was passed without brackets. That means that 'nobrackets'
// is correct but 'brackets' is not.
brackets = STRINGIZE('[' << brackets << ']');
}
else
{
// key was passed with brackets. That means that 'brackets' is
// correct but 'nobrackets' is not. Erase the left bracket.
nobrackets.erase(0, 1);
std::string::size_type length(nobrackets.length());
if (length && nobrackets[length - 1] == ']')
{
nobrackets.erase(length - 1);
}
}
// Calling LLTrans::getString() is what embeds the other default
// translation strings into this one.
LLTrans::setDefaultArg(brackets, LLTrans::getString(nobrackets));
}
}
//
// This function decides whether the client machine meets the minimum requirements to
// run in a maximized window, per the consensus of davep, boa and nyx on 3/30/2011.
//
bool LLAppViewer::meetsRequirementsForMaximizedStart()
{
bool maximizedOk = (LLFeatureManager::getInstance()->getGPUClass() >= GPU_CLASS_2);
maximizedOk &= (gSysMemory.getPhysicalMemoryKB() >= U32Gigabytes(1));
Steven Bennetts
committed
bool LLAppViewer::initWindow()
{
LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
Steven Bennetts
committed
// store setting in a global for easy access and modification
gHeadlessClient = gSavedSettings.getBOOL("HeadlessClient");
Steven Bennetts
committed
// always start windowed
BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
callum
committed
LLViewerWindow::Params window_params;
window_params
.title(gWindowTitle)
.name(VIEWER_WINDOW_CLASSNAME)
.x(gSavedSettings.getS32("WindowX"))
.y(gSavedSettings.getS32("WindowY"))