From 5aa43e4f3e30d81fb518783189b3258e67b4620a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 22 Feb 2011 19:30:50 -0800
Subject: [PATCH] SOCIAL-545 WIP Figure out how to configure skylight-specific
 settings while retaining relevant user settings (login account name, etc.)
 converted settings_file.xml to use param block descriptions for easier
 modification added session settings file and user session settings file for
 per-session config overrides

---
 indra/llxml/llcontrol.cpp                     |   5 +-
 indra/llxml/llcontrol.h                       |   2 +-
 indra/newview/app_settings/cmd_line.xml       |  18 ++
 indra/newview/app_settings/settings.xml       |  26 ++-
 indra/newview/app_settings/settings_files.xml | 212 +++++------------
 indra/newview/llappviewer.cpp                 | 219 ++++++++++++------
 indra/newview/llappviewer.h                   |   2 +-
 7 files changed, 257 insertions(+), 227 deletions(-)

diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 6c726091223..6e4364a20d2 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -835,7 +835,7 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only
 	return num_saved;
 }
 
-U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values)
+U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values)
 {
 	std::string name;
 	LLSD settings;
@@ -908,8 +908,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 			}
 			else if(existing_control->isPersisted())
 			{
-				
-				existing_control->setValue(control_map["Value"]);
+				existing_control->setValue(control_map["Value"], save_values);
 			}
 			// *NOTE: If not persisted and not setting defaults, 
 			// the value should not get loaded.
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 93975579ccd..e402061e1f5 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -289,7 +289,7 @@ class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
 	// as the given type.
 	U32	loadFromFileLegacy(const std::string& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
  	U32 saveToFile(const std::string& filename, BOOL nondefault_only);
- 	U32	loadFromFile(const std::string& filename, bool default_values = false);
+ 	U32	loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
 	void	resetToDefaults();
 };
 
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index e4ac455e7cb..89e5949fbe9 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -261,6 +261,24 @@
       <!-- Special case. Mapped to settings procedurally. -->
     </map>
 
+    <key>sessionsettings</key>
+    <map>
+      <key>desc</key>
+      <string>Specify the filename of a configuration file that contains temporary per-session configuration overrides.</string>
+      <key>count</key>
+      <integer>1</integer>
+      <!-- Special case. Mapped to settings procedurally. -->
+    </map>
+
+    <key>usersessionsettings</key>
+    <map>
+      <key>desc</key>
+      <string>Specify the filename of a configuration file that contains temporary per-session configuration user overrides.</string>
+      <key>count</key>
+      <integer>1</integer>
+      <!-- Special case. Mapped to settings procedurally. -->
+    </map>
+    
     <key>login</key>
     <map>
       <key>desc</key>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 6630d8f4003..1bcc988e5c2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11473,7 +11473,7 @@
       <key>Type</key>
       <string>F32</string>
       <key>Value</key>
-      <integer>3.0</integer>
+      <integer>3</integer>
     </map>
     <key>InterpolationPhaseOut</key>
     <map>
@@ -11484,7 +11484,7 @@
       <key>Type</key>
       <string>F32</string>
       <key>Value</key>
-      <integer>1.0</integer>
+      <integer>1</integer>
     </map>
     <key>VerboseLogs</key>
     <map>
@@ -12366,5 +12366,27 @@
       <key>Value</key>
       <string>name</string>
     </map>
+    <key>SessionSettingsFile</key>
+    <map>
+      <key>Comment</key>
+      <string>Settings that are a applied per session (not saved).</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string />
+    </map>
+    <key>UserSessionSettingsFile</key>
+    <map>
+      <key>Comment</key>
+      <string>User settings that are a applied per session (not saved).</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string />
+    </map>
 </map>
 </llsd>
diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml
index aa5b301959c..079a54f9578 100644
--- a/indra/newview/app_settings/settings_files.xml
+++ b/indra/newview/app_settings/settings_files.xml
@@ -1,148 +1,64 @@
-<llsd>
-  <map>
-    <key>Locations</key>
-    <map>
-      <!--
-      The Locations LLSD block specifies the usage pattern of 
-      the settings file types
-      Each location is represented by a LLSD containing the following values:
-      PathIndex = hard coded path indicies.
-      Files = map of files to load
-        Each file can have:
-        Requirement = level of necessity for loading. 
-          0 ( or Req. no key) = do not load
-          1 = required, fail if not found
-        NameFromSetting = Use the given setting to specify the name. Not valid for
-                          "Default"
-      -->
-      <key>Comment</key>
-      <string>List location from which to load files, and the rules about loading those files.</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>LLSD</string>
-      <key>Value</key>
-      <map>
-        <key>Default</key>
-        <map>
-          <key>PathIndex</key>
-          <integer>2</integer>
-          <key>Files</key>
-          <map>
-            <key>Global</key>
-            <map>
-              <key>Name</key>
-              <string>settings.xml</string>
-              <key>Requirement</key>
-              <integer>1</integer>
-            </map>
-            <key>PerAccount</key>
-            <map>
-              <key>Name</key>
-              <string>settings_per_account.xml</string>
-              <key>Requirement</key>
-              <integer>1</integer>
-            </map>
-            <key>CrashSettings</key>
-            <map>
-              <key>Name</key>
-              <string>settings_crash_behavior.xml</string>
-              <key>Requirement</key>
-              <integer>1</integer>
-            </map>
-            <key>Warnings</key>
-            <map>
-              <key>Name</key>
-              <string>ignorable_dialogs.xml</string>
-              <key>Requirement</key>
-              <integer>1</integer>
-            </map>
-          </map>
-        </map>
-        <key>User</key>
-        <map>
-          <key>PathIndex</key>
-          <integer>1</integer>
-          <key>Files</key>
-          <map>
-            <key>Global</key>
-            <map>
-              <key>Name</key>
-              <string>settings.xml</string>
-              <key>NameFromSetting</key>
-              <string>ClientSettingsFile</string>
-            </map>
-            <key>CrashSettings</key>
-            <map>
-              <key>Name</key>
-              <string>settings_crash_behavior.xml</string>
-            </map>
-            <key>Warnings</key>
-            <map>
-              <key>Name</key>
-              <string>ignorable_dialogs.xml</string>
-              <key>NameFromSetting</key>
-              <string>WarningSettingsFile</string>
-            </map>
-          </map>
-        </map>
-        <key>Account</key>
-        <map>
-          <key>PathIndex</key>
-          <integer>3</integer>
-          <key>Files</key>
-          <map>
-            <key>PerAccount</key>
-            <map>
-              <key>Name</key>
-              <string>settings_per_account.xml</string>
-              <key>NameFromSetting</key>
-              <string>PerAccountSettingsFile</string>
-            </map>
-          </map>
-        </map>
-        <key>DefaultSkin</key>
-        <map>
-          <key>PathIndex</key>
-          <integer>17</integer>
-          <key>Files</key>
-          <map>
-            <key>Skinning</key>
-            <map>
-              <key>Name</key>
-              <string>colors.xml</string>
-            </map>
-          </map>
-        </map>
-        <key>CurrentSkin</key>
-        <map>
-          <key>PathIndex</key>
-          <integer>10</integer>
-          <key>Files</key>
-          <map>
-            <key>Skinning</key>
-            <map>
-              <key>Name</key>
-              <string>colors.xml</string>
-            </map>
-          </map>
-        </map>
-        <key>UserSkin</key>
-        <map>
-          <key>PathIndex</key>
-          <integer>14</integer>
-          <key>Files</key>
-          <map>
-            <key>Skinning</key>
-            <map>
-              <key>Name</key>
-              <string>colors.xml</string>
-              <key>NameFromSetting</key>
-              <string>SkinningSettingsFile</string>
-            </map>
-          </map>
-        </map>
-      </map>
-    </map>
-  </map>
-</llsd>
+<settings_files>
+  <group name="Default"
+         path_index="2">
+    <file name="Global"
+          file_name="settings.xml"
+          required="true"/>
+    <file name="PerAccount"
+          file_name="settings_per_account.xml"
+          required="true"/>
+    <file name="CrashSettings"
+          file_name="settings_crash_behavior.xml"
+          required="true"/>
+    <file name="Warnings"
+          file_name="ignorable_dialogs.xml"
+          required="true"/>
+  </group>
+  <group name="User"
+         path_index="1">
+    <file name="Global"
+          file_name="settings.xml"
+          file_name_setting="ClientSettingsFile"/>
+    <file name="CrashSettings"
+          file_name="settings_crash_behavior"/>
+    <file name="Warnings"
+          file_name="ignorable_dialogs.xml"
+          file_name_setting="WarningSettingsFile"/>
+  </group>
+  <group name="Account"
+         path_index="3">
+    <file name="PerAccount"
+          file_name="settings_per_account.xml"
+          file_name_setting="PerAccountSettingsFile"/>
+  </group>
+  <group name="Session"
+         path_index="2">
+      <file name="Global"
+            file_name="session.xml" 
+            file_name_setting="SessionSettingsFile"
+            persistent="false"/>
+  </group>
+  <group name="UserSession"
+         path_index="1">
+    <file name="Global"
+          file_name="session.xml" 
+          file_name_setting="UserSessionSettingsFile"
+          persistent="false"/>
+  </group>
+  <group name="DefaultSkin"
+         path_index="17">
+    <file name="Skinning"
+          file_name="colors.xml"/>
+  </group>
+  <group name="CurrentSkin"
+         path_index="10">
+    <file name="Skinning"
+          file_name="colors.xml"/>
+  </group>
+  <group name="UserSkin"
+         path_index="14">
+    <file name="Skinning"
+          file_name="colors.xml"
+          file_name_setting="SkinningSettingsFile"/>
+  </group>
+</settings_files>
\ No newline at end of file
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a23f809b712..c285ddc2f69 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -337,6 +337,46 @@ void init_default_trans_args()
 const char *VFS_DATA_FILE_BASE = "data.db2.x.";
 const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
 
+
+struct SettingsFile : public LLInitParam::Block<SettingsFile>
+{
+	Mandatory<std::string>	name;
+	Optional<std::string>	file_name;
+	Optional<bool>			required,
+							persistent;
+	Optional<std::string>	file_name_setting;
+
+	SettingsFile()
+	:	name("name"),
+		file_name("file_name"),
+		required("required", false),
+		persistent("persistent", true),
+		file_name_setting("file_name_setting")
+	{}
+};
+
+struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
+{
+	Mandatory<std::string>	name;
+	Mandatory<S32>			path_index;
+	Multiple<SettingsFile>	files;
+
+	SettingsGroup()
+	:	name("name"),
+		path_index("path_index"),
+		files("file")
+	{}
+};
+
+struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
+{
+	Multiple<SettingsGroup>	groups;
+
+	SettingsFiles()
+	: groups("group")
+	{}
+};
+
 static std::string gWindowTitle;
 
 LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
@@ -594,7 +634,8 @@ LLAppViewer::LLAppViewer() :
 	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
 	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
 	mFastTimerLogThread(NULL),
-	mUpdater(new LLUpdaterService())
+	mUpdater(new LLUpdaterService()),
+	mSettingsLocationList(NULL)
 {
 	if(NULL != sInstance)
 	{
@@ -610,6 +651,8 @@ LLAppViewer::LLAppViewer() :
 
 LLAppViewer::~LLAppViewer()
 {
+	delete mSettingsLocationList;
+
 	LLLoginInstance::instance().setUpdaterService(0);
 	
 	destroyMainloopTimeout();
@@ -1879,85 +1922,72 @@ bool LLAppViewer::initLogging()
 bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
 					    bool set_defaults)
 {	
-	// Find and vet the location key.
-	if(!mSettingsLocationList.has(location_key))
+	if (!mSettingsLocationList)
 	{
-		llerrs << "Requested unknown location: " << location_key << llendl;
-		return false;
+		llerrs << "Invalid settings location list" << llendl;
 	}
 
-	LLSD location = mSettingsLocationList.get(location_key);
-
-	if(!location.has("PathIndex"))
-	{
-		llerrs << "Settings location is missing PathIndex value. Settings cannot be loaded." << llendl;
-		return false;
-	}
-	ELLPath path_index = (ELLPath)(location.get("PathIndex").asInteger());
-	if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
+	LLControlGroup* global_settings = LLControlGroup::getInstance(sGlobalSettingsName);  
+	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
+		it != end_it;
+		++it)
 	{
-		llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
-		return false;
-	}
-
-	// Iterate through the locations list of files.
-	LLSD files = location.get("Files");
-	for(LLSD::map_iterator itr = files.beginMap(); itr != files.endMap(); ++itr)
-	{
-		std::string settings_group = (*itr).first;
-		llinfos << "Attempting to load settings for the group " << settings_group 
-			    << " - from location " << location_key << llendl;
+		if (it->name() != location_key) continue;
 
-		if(!LLControlGroup::getInstance(settings_group))
+		ELLPath path_index = (ELLPath)it->path_index();
+		if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
 		{
-			llwarns << "No matching settings group for name " << settings_group << llendl;
-			continue;
+			llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
+			return false;
 		}
 
-		LLSD file = (*itr).second;
-
-		std::string full_settings_path;
-		if(file.has("NameFromSetting"))
+		LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
+		for (file_it = it->files.begin(), end_file_it = it->files.end();
+			file_it != end_file_it;
+			++file_it)
 		{
-			std::string custom_name_setting = file.get("NameFromSetting");
-			// *NOTE: Regardless of the group currently being lodaed,
-			// this setting is always read from the Global settings.
-			if(LLControlGroup::getInstance(sGlobalSettingsName)->controlExists(custom_name_setting))
+			llinfos << "Attempting to load settings for the group " << file_it->name()
+			    << " - from location " << location_key << llendl;
+
+			LLControlGroup* settings_group = LLControlGroup::getInstance(file_it->name);
+			if(!settings_group)
 			{
-				std::string file_name = 
-					LLControlGroup::getInstance(sGlobalSettingsName)->getString(custom_name_setting);
-				full_settings_path = file_name;
+				llwarns << "No matching settings group for name " << file_it->name() << llendl;
+				continue;
 			}
-		}
 
-		if(full_settings_path.empty())
-		{
-			std::string file_name = file.get("Name");
-			full_settings_path = gDirUtilp->getExpandedFilename(path_index, file_name);
-		}
+			std::string full_settings_path;
 
-		int requirement = 0;
-		if(file.has("Requirement"))
-		{
-			requirement = file.get("Requirement").asInteger();
-		}
-		
-		if(!LLControlGroup::getInstance(settings_group)->loadFromFile(full_settings_path, set_defaults))
-		{
-			if(requirement == 1)
+			if (file_it->file_name_setting.isProvided() 
+				&& global_settings->controlExists(file_it->file_name_setting))
 			{
-				llwarns << "Error: Cannot load required settings file from: " 
-						<< full_settings_path << llendl;
-				return false;
+				full_settings_path = global_settings->getString(file_it->file_name_setting);
 			}
 			else
 			{
-				llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
+				full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file_it->file_name());
+			}
+
+			if(!settings_group->loadFromFile(full_settings_path, set_defaults, file_it->persistent))
+			{
+				if(file_it->required)
+				{
+					llwarns << "Error: Cannot load required settings file from: " 
+							<< full_settings_path << llendl;
+					return false;
+				}
+				else
+				{
+					if (!full_settings_path.empty())
+					{
+						llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
+					}
+				}
+			}
+			else
+			{
+				llinfos << "Loaded settings file " << full_settings_path << llendl;
 			}
-		}
-		else
-		{
-			llinfos << "Loaded settings file " << full_settings_path << llendl;
 		}
 	}
 
@@ -1967,18 +1997,25 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
 std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
 											 const std::string& file)
 {
-	if(mSettingsLocationList.has(location_key))
+	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
+		it != end_it;
+		++it)
 	{
-		LLSD location = mSettingsLocationList.get(location_key);
-		if(location.has("Files"))
+		if (it->name() == location_key)
 		{
-			LLSD files = location.get("Files");
-			if(files.has(file) && files[file].has("Name"))
+			LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
+			for (file_it = it->files.begin(), end_file_it = it->files.end();
+				file_it != end_file_it;
+				++file_it)
 			{
-				return files.get(file).get("Name").asString();
+				if (file_it->name() == file)
+				{
+					return file_it->file_name;
+				}
 			}
 		}
 	}
+
 	return std::string();
 }
 
@@ -1991,14 +2028,29 @@ bool LLAppViewer::initConfiguration()
 {	
 	//Load settings files list
 	std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
-	LLControlGroup settings_control("SettingsFiles");
-	llinfos << "Loading settings file list " << settings_file_list << llendl;
-	if (0 == settings_control.loadFromFile(settings_file_list))
+	//LLControlGroup settings_control("SettingsFiles");
+	//llinfos << "Loading settings file list " << settings_file_list << llendl;
+	//if (0 == settings_control.loadFromFile(settings_file_list))
+	//{
+ //       llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
+	//}
+
+	LLXMLNodePtr root;
+	BOOL success  = LLXMLNode::parseFile(settings_file_list, root, NULL);
+	if (!success)
 	{
         llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
 	}
 
-	mSettingsLocationList = settings_control.getLLSD("Locations");
+	mSettingsLocationList = new SettingsFiles();
+
+	LLXUIParser parser;
+	parser.readXUI(root, *mSettingsLocationList, settings_file_list);
+
+	if (!mSettingsLocationList->validateBlock())
+	{
+        llerrs << "Invalid settings file list " << settings_file_list << llendl;
+	}
 		
 	// The settings and command line parsing have a fragile
 	// order-of-operation:
@@ -2105,6 +2157,29 @@ bool LLAppViewer::initConfiguration()
 			<< user_settings_filename << llendl;
 	}
 
+	if (clp.hasOption("sessionsettings"))
+	{
+		std::string session_settings_filename = 
+			gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, 
+										   clp.getOption("sessionsettings")[0]);		
+		gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
+		llinfos	<< "Using session settings filename: " 
+			<< session_settings_filename << llendl;
+	}
+	loadSettingsFromDirectory("Session");
+
+	if (clp.hasOption("usersessionsettings"))
+	{
+		std::string user_session_settings_filename = 
+			gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, 
+										   clp.getOption("usersessionsettings")[0]);		
+		gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
+		llinfos	<< "Using user session settings filename: " 
+			<< user_session_settings_filename << llendl;
+
+	}
+	loadSettingsFromDirectory("UserSession");
+
 	// - load overrides from user_settings 
 	loadSettingsFromDirectory("User");
 	// - apply command line settings 
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index a18e6cbb028..0226211735f 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -253,7 +253,7 @@ class LLAppViewer : public LLApp
     bool mQuitRequested;				// User wants to quit, may have modified documents open.
     bool mLogoutRequestSent;			// Disconnect message sent to simulator, no longer safe to send messages to the sim.
     S32 mYieldTime;
-	LLSD mSettingsLocationList;
+	struct SettingsFiles* mSettingsLocationList;
 
 	LLWatchdogTimeout* mMainloopTimeout;
 
-- 
GitLab