Procházet zdrojové kódy

UI: Fix crash when providing scene collection or profile via CLI

When a starting scene collection or profile is provided, current code
would crash as the corresponding collections and management functions
do not exist yet (they are tied to OBSBasic, which is not initialized
that early in the program execution).

This change moves the checks for command line arguments into OBSBasic
into the parts responsible for initializing profiles and scene
collections and check for arguments provided via command line there.
PatTheMav před 1 rokem
rodič
revize
3995b4662d
3 změnil soubory, kde provedl 37 přidání a 64 odebrání
  1. 5 37
      UI/obs-app.cpp
  2. 1 1
      UI/obs-app.hpp
  3. 31 26
      UI/window-basic-main.cpp

+ 5 - 37
UI/obs-app.cpp

@@ -677,8 +677,6 @@ bool OBSApp::InitGlobalConfig()
 
 bool OBSApp::InitUserConfig(std::filesystem::path &userConfigLocation, uint32_t lastVersion)
 {
-	bool hasChanges = false;
-
 	const std::string userConfigFile = userConfigLocation.u8string() + "/obs-studio/user.ini";
 
 	int errorCode = userConfig.Open(userConfigFile.c_str(), CONFIG_OPEN_ALWAYS);
@@ -688,45 +686,13 @@ bool OBSApp::InitUserConfig(std::filesystem::path &userConfigLocation, uint32_t
 		return false;
 	}
 
-	hasChanges = MigrateLegacySettings(lastVersion);
-
-	if (!opt_starting_collection.empty()) {
-		const OBSBasic *basic = reinterpret_cast<OBSBasic *>(GetMainWindow());
-		const std::optional<OBSSceneCollection> foundCollection =
-			basic->GetSceneCollectionByName(opt_starting_collection);
-
-		if (foundCollection) {
-			config_set_string(userConfig, "Basic", "SceneCollection", foundCollection.value().name.c_str());
-			config_set_string(userConfig, "Basic", "SceneCollectionFile",
-					  foundCollection.value().fileName.c_str());
-			hasChanges = true;
-		}
-	}
-
-	if (!opt_starting_profile.empty()) {
-		const OBSBasic *basic = reinterpret_cast<OBSBasic *>(GetMainWindow());
-
-		const std::optional<OBSProfile> foundProfile = basic->GetProfileByName(opt_starting_profile);
-
-		if (foundProfile) {
-			config_set_string(userConfig, "Basic", "Profile", foundProfile.value().name.c_str());
-			config_set_string(userConfig, "Basic", "ProfileDir",
-					  foundProfile.value().directoryName.c_str());
-
-			hasChanges = true;
-		}
-	}
-
-	if (hasChanges) {
-		config_save_safe(userConfig, "tmp", nullptr);
-	}
-
+	MigrateLegacySettings(lastVersion);
 	InitUserConfigDefaults();
 
 	return true;
 }
 
-bool OBSApp::MigrateLegacySettings(const uint32_t lastVersion)
+void OBSApp::MigrateLegacySettings(const uint32_t lastVersion)
 {
 	bool hasChanges = false;
 
@@ -766,7 +732,9 @@ bool OBSApp::MigrateLegacySettings(const uint32_t lastVersion)
 		hasChanges = true;
 	}
 
-	return hasChanges;
+	if (hasChanges) {
+		userConfig.SaveSafe("tmp");
+	}
 }
 
 static constexpr string_view OBSGlobalIniPath = "/obs-studio/global.ini";

+ 1 - 1
UI/obs-app.hpp

@@ -113,7 +113,7 @@ private:
 	bool InitGlobalLocationDefaults();
 
 	bool MigrateGlobalSettings();
-	bool MigrateLegacySettings(uint32_t lastVersion);
+	void MigrateLegacySettings(uint32_t lastVersion);
 
 	bool InitUserConfig(std::filesystem::path &userConfigLocation, uint32_t lastVersion);
 	void InitUserConfigDefaults();

+ 31 - 26
UI/window-basic-main.cpp

@@ -121,6 +121,9 @@ QCef *cef = nullptr;
 QCefCookieManager *panel_cookies = nullptr;
 bool cef_js_avail = false;
 
+extern std::string opt_starting_profile;
+extern std::string opt_starting_collection;
+
 void DestroyPanelCookieManager();
 
 namespace {
@@ -1876,22 +1879,21 @@ bool OBSBasic::InitBasicConfig()
 
 	RefreshProfiles(true);
 
-	std::string currentProfileName{config_get_string(App()->GetUserConfig(), "Basic", "Profile")};
-
-	auto foundProfile = GetProfileByName(currentProfileName);
+	const std::string currentProfileName{config_get_string(App()->GetUserConfig(), "Basic", "Profile")};
+	const std::optional<OBSProfile> currentProfile = GetProfileByName(currentProfileName);
+	const std::optional<OBSProfile> foundProfile = GetProfileByName(opt_starting_profile);
 
-	if (!foundProfile) {
-		const OBSProfile &newProfile = CreateProfile(currentProfileName);
-
-		ActivateProfile(newProfile);
-	} else {
-		// TODO: Remove duplicate code from OBS initialization and just use ActivateProfile here instead
-		int code = activeConfiguration.Open(foundProfile.value().profileFile.u8string().c_str(),
-						    CONFIG_OPEN_ALWAYS);
-		if (code != CONFIG_SUCCESS) {
-			OBSErrorBox(NULL, "Failed to open basic.ini: %d", code);
-			return false;
+	try {
+		if (foundProfile) {
+			ActivateProfile(foundProfile.value());
+		} else if (currentProfile) {
+			ActivateProfile(currentProfile.value());
+		} else {
+			SetupNewProfile(currentProfileName);
 		}
+	} catch (const std::logic_error &) {
+		OBSErrorBox(NULL, "Failed to open basic.ini: %d", -1);
+		return false;
 	}
 
 	return InitBasicConfigDefaults();
@@ -2170,19 +2172,22 @@ void OBSBasic::OBSInit()
 
 	{
 		ProfileScope("OBSBasic::Load");
-		disableSaving--;
-
-		try {
-			const OBSSceneCollection &currentCollection = GetCurrentSceneCollection();
-			ActivateSceneCollection(currentCollection);
-		} catch (const std::invalid_argument &) {
-			const std::string collectionName =
-				config_get_string(App()->GetUserConfig(), "Basic", "SceneCollection");
-
-			SetupNewSceneCollection(collectionName);
+		const std::string sceneCollectionName{
+			config_get_string(App()->GetUserConfig(), "Basic", "SceneCollection")};
+		const std::optional<OBSSceneCollection> configuredCollection =
+			GetSceneCollectionByName(sceneCollectionName);
+		const std::optional<OBSSceneCollection> foundCollection =
+			GetSceneCollectionByName(opt_starting_collection);
+
+		if (foundCollection) {
+			ActivateSceneCollection(foundCollection.value());
+		} else if (configuredCollection) {
+			ActivateSceneCollection(configuredCollection.value());
+		} else {
+			disableSaving--;
+			SetupNewSceneCollection(sceneCollectionName);
+			disableSaving++;
 		}
-
-		disableSaving++;
 	}
 
 	loaded = true;