Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions frontend/OBSApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <plugin-manager/PluginManager.hpp>
#include <utility/CrashHandler.hpp>
#include <utility/OBSEventFilter.hpp>
#include <utility/OBSInitException.hpp>
#include <utility/OBSProxyStyle.hpp>
#if defined(_WIN32) || defined(ENABLE_SPARKLE_UPDATER)
#include <utility/models/branches.hpp>
Expand Down Expand Up @@ -1081,16 +1082,16 @@ void OBSApp::AppInit()
QAccessible::installFactory(alignmentSelectorFactory);

if (!MakeUserDirs()) {
throw "Failed to create required user directories";
throw OBSInitException(OBSInitErrorCode::UserDirs, "Failed to create required user directories");
}
if (!InitGlobalConfig()) {
throw "Failed to initialize global config";
throw OBSInitException(OBSInitErrorCode::GlobalConfig, "Failed to initialize global config");
}
if (!InitLocale()) {
throw "Failed to load locale";
throw OBSInitException(OBSInitErrorCode::Locale, "Failed to load locale");
}
if (!InitTheme()) {
throw "Failed to load theme";
throw OBSInitException(OBSInitErrorCode::Theme, "Failed to load theme");
}

config_set_default_string(userConfig, "Basic", "Profile", Str("Untitled"));
Expand Down Expand Up @@ -1132,7 +1133,7 @@ void OBSApp::AppInit()
move_basic_to_scene_collections();

if (!MakeUserProfileDirs()) {
throw "Failed to create profile directories";
throw OBSInitException(OBSInitErrorCode::ProfileDirs, "Failed to create profile directories");
}
}

Expand Down Expand Up @@ -1687,12 +1688,12 @@ vector<pair<string, string>> GetLocaleNames()
{
string path;
if (!GetDataFilePath("locale.ini", path)) {
throw "Could not find locale.ini path";
throw OBSInitException(OBSInitErrorCode::LocaleIniPath, "Could not find locale.ini path");
}

ConfigFile ini;
if (ini.Open(path.c_str(), CONFIG_OPEN_EXISTING) != 0) {
throw "Could not open locale.ini";
throw OBSInitException(OBSInitErrorCode::LocaleIniOpen, "Could not open locale.ini");
}

size_t sections = config_num_sections(ini);
Expand Down
2 changes: 2 additions & 0 deletions frontend/cmake/ui-utility.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ target_sources(
utility/MissingFilesPathItemDelegate.hpp
utility/MultitrackVideoError.cpp
utility/MultitrackVideoError.hpp
utility/OBSInitException.cpp
utility/OBSInitException.hpp
utility/MultitrackVideoOutput.cpp
utility/MultitrackVideoOutput.hpp
utility/NativeEventFilter.hpp
Expand Down
10 changes: 10 additions & 0 deletions frontend/data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
# Language of this file
Language="English"

# Startup / initialization errors
Init.Error.UserDirs="Failed to create required user directories."
Init.Error.GlobalConfig="Failed to initialize the global configuration."
Init.Error.Locale="Failed to load the application language files."
Init.Error.Theme="Failed to load the application theme."
Init.Error.ProfileDirs="Failed to create profile directories."
Init.Error.LocaleIniPath="Could not find the locale.ini path."
Init.Error.LocaleIniOpen="Could not open locale.ini."
Init.Error.Unknown="OBS Studio failed to start."

# commonly shared locale
OK="OK"
Apply="Apply"
Expand Down
4 changes: 4 additions & 0 deletions frontend/obs-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <dialogs/OBSPermissions.hpp>
#endif
#include <utility/BaseLexer.hpp>
#include <utility/OBSInitException.hpp>
#include <utility/OBSTranslator.hpp>
#include <utility/platform.hpp>

Expand Down Expand Up @@ -690,6 +691,9 @@ static int run_program(fstream &logFile, int argc, char *argv[])

ret = program.exec();

} catch (const OBSInitException &error) {
blog(LOG_ERROR, "OBS init failed (%s): %s", OBSInitException::codeName(error.code()), error.what());
OBSErrorBox(nullptr, "%s", QT_TO_UTF8(error.localizedMessage()));
} catch (const char *error) {
blog(LOG_ERROR, "%s", error);
OBSErrorBox(nullptr, "%s", error);
Expand Down
42 changes: 42 additions & 0 deletions frontend/utility/OBSInitException.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/******************************************************************************
Copyright (C) 2026 by Ray Winkelman <rwinkelman@users.noreply.github.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include "OBSInitException.hpp"

#include "OBSApp.hpp"

QString OBSInitException::localizedMessage() const
{
switch (code_) {
case OBSInitErrorCode::UserDirs:
return QTStr("Init.Error.UserDirs");
case OBSInitErrorCode::GlobalConfig:
return QTStr("Init.Error.GlobalConfig");
case OBSInitErrorCode::Locale:
return QTStr("Init.Error.Locale");
case OBSInitErrorCode::Theme:
return QTStr("Init.Error.Theme");
case OBSInitErrorCode::ProfileDirs:
return QTStr("Init.Error.ProfileDirs");
case OBSInitErrorCode::LocaleIniPath:
return QTStr("Init.Error.LocaleIniPath");
case OBSInitErrorCode::LocaleIniOpen:
return QTStr("Init.Error.LocaleIniOpen");
}

return QTStr("Init.Error.Unknown");
}
74 changes: 74 additions & 0 deletions frontend/utility/OBSInitException.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/******************************************************************************
Copyright (C) 2026 by Ray Winkelman <rwinkelman@users.noreply.github.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#pragma once

#include <QString>

#include <exception>
#include <string>
#include <utility>

enum class OBSInitErrorCode {
UserDirs,
GlobalConfig,
Locale,
Theme,
ProfileDirs,
LocaleIniPath,
LocaleIniOpen,
};

class OBSInitException : public std::exception {
public:
explicit OBSInitException(OBSInitErrorCode code, std::string detail = {})
: code_(code),
detail_(std::move(detail))
{
}

OBSInitErrorCode code() const { return code_; }

const char *what() const noexcept override { return detail_.empty() ? codeName(code_) : detail_.c_str(); }

QString localizedMessage() const;

static const char *codeName(OBSInitErrorCode code)
{
switch (code) {
case OBSInitErrorCode::UserDirs:
return "UserDirs";
case OBSInitErrorCode::GlobalConfig:
return "GlobalConfig";
case OBSInitErrorCode::Locale:
return "Locale";
case OBSInitErrorCode::Theme:
return "Theme";
case OBSInitErrorCode::ProfileDirs:
return "ProfileDirs";
case OBSInitErrorCode::LocaleIniPath:
return "LocaleIniPath";
case OBSInitErrorCode::LocaleIniOpen:
return "LocaleIniOpen";
}
return "Unknown";
}

private:
OBSInitErrorCode code_;
std::string detail_;
};