mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-08-24 02:34:23 -05:00
Update C++ files with braces
This commit is contained in:
+141
-73
@@ -143,9 +143,10 @@ UncleanLaunchAction handleUncleanShutdown(bool enableCrashUpload)
|
||||
QAccessibleInterface *alignmentSelectorFactory(const QString &classname, QObject *object)
|
||||
{
|
||||
if (classname == QLatin1String("AlignmentSelector")) {
|
||||
if (auto *w = qobject_cast<AlignmentSelector *>(object))
|
||||
if (auto *w = qobject_cast<AlignmentSelector *>(object)) {
|
||||
return new AccessibleAlignmentSelector(w);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
@@ -154,8 +155,9 @@ QObject *CreateShortcutFilter()
|
||||
{
|
||||
return new OBSEventFilter([](QObject *obj, QEvent *event) {
|
||||
auto mouse_event = [](QMouseEvent &event) {
|
||||
if (!App()->HotkeysEnabledInFocus() && event.button() != Qt::LeftButton)
|
||||
if (!App()->HotkeysEnabledInFocus() && event.button() != Qt::LeftButton) {
|
||||
return true;
|
||||
}
|
||||
|
||||
obs_key_combination_t hotkey = {0, OBS_KEY_NONE};
|
||||
bool pressed = event.type() == QEvent::MouseButtonPress;
|
||||
@@ -407,37 +409,49 @@ static bool MakeUserDirs()
|
||||
{
|
||||
char path[512];
|
||||
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/basic") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/basic") <= 0) {
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
}
|
||||
if (!do_mkdir(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/logs") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/logs") <= 0) {
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
}
|
||||
if (!do_mkdir(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/profiler_data") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/profiler_data") <= 0) {
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
}
|
||||
if (!do_mkdir(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/crashes") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/crashes") <= 0) {
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
}
|
||||
if (!do_mkdir(path)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/updates") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/updates") <= 0) {
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
}
|
||||
if (!do_mkdir(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/plugin_config") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/plugin_config") <= 0) {
|
||||
return false;
|
||||
if (!do_mkdir(path))
|
||||
}
|
||||
if (!do_mkdir(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -490,8 +504,9 @@ static bool MakeUserProfileDirs()
|
||||
|
||||
bool OBSApp::UpdatePre22MultiviewLayout(const char *layout)
|
||||
{
|
||||
if (!layout)
|
||||
if (!layout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (astrcmpi(layout, "horizontaltop") == 0) {
|
||||
config_set_int(userConfig, "BasicWindow", "MultiviewLayout",
|
||||
@@ -703,14 +718,16 @@ bool OBSApp::InitLocale()
|
||||
|
||||
const char *lang = config_get_string(userConfig, "General", "Language");
|
||||
bool userLocale = config_has_user_value(userConfig, "General", "Language");
|
||||
if (!userLocale || !lang || lang[0] == '\0')
|
||||
if (!userLocale || !lang || lang[0] == '\0') {
|
||||
lang = DEFAULT_LANG;
|
||||
}
|
||||
|
||||
locale = lang;
|
||||
|
||||
// set basic default application locale
|
||||
if (!locale.empty())
|
||||
if (!locale.empty()) {
|
||||
QLocale::setDefault(QLocale(QString::fromStdString(locale).replace('-', '_')));
|
||||
}
|
||||
|
||||
string englishPath;
|
||||
if (!GetDataFilePath("locale/" DEFAULT_LANG ".ini", englishPath)) {
|
||||
@@ -726,30 +743,35 @@ bool OBSApp::InitLocale()
|
||||
|
||||
bool defaultLang = astrcmpi(lang, DEFAULT_LANG) == 0;
|
||||
|
||||
if (userLocale && defaultLang)
|
||||
if (userLocale && defaultLang) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!userLocale && defaultLang) {
|
||||
for (auto &locale_ : GetPreferredLocales()) {
|
||||
if (locale_ == lang)
|
||||
if (locale_ == lang) {
|
||||
return true;
|
||||
}
|
||||
|
||||
stringstream file;
|
||||
file << "locale/" << locale_ << ".ini";
|
||||
|
||||
string path;
|
||||
if (!GetDataFilePath(file.str().c_str(), path))
|
||||
if (!GetDataFilePath(file.str().c_str(), path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!text_lookup_add(textLookup, path.c_str()))
|
||||
if (!text_lookup_add(textLookup, path.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "Using preferred locale '%s'", locale_.c_str());
|
||||
locale = locale_;
|
||||
|
||||
// set application default locale to the new chosen one
|
||||
if (!locale.empty())
|
||||
if (!locale.empty()) {
|
||||
QLocale::setDefault(QLocale(QString::fromStdString(locale).replace('-', '_')));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -762,8 +784,9 @@ bool OBSApp::InitLocale()
|
||||
|
||||
string path;
|
||||
if (GetDataFilePath(file.str().c_str(), path)) {
|
||||
if (!text_lookup_add(textLookup, path.c_str()))
|
||||
if (!text_lookup_add(textLookup, path.c_str())) {
|
||||
blog(LOG_ERROR, "Failed to add locale file '%s'", path.c_str());
|
||||
}
|
||||
} else {
|
||||
blog(LOG_ERROR, "Could not find locale file '%s'", file.str().c_str());
|
||||
}
|
||||
@@ -786,11 +809,13 @@ void ParseBranchesJson(const std::string &jsonString, vector<UpdateBranch> &out,
|
||||
|
||||
for (const JsonBranch &json_branch : branches) {
|
||||
#ifdef _WIN32
|
||||
if (!json_branch.windows)
|
||||
if (!json_branch.windows) {
|
||||
continue;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
if (!json_branch.macos)
|
||||
if (!json_branch.macos) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
UpdateBranch branch = {
|
||||
@@ -824,8 +849,9 @@ bool LoadBranchesFile(vector<UpdateBranch> &out)
|
||||
}
|
||||
|
||||
ParseBranchesJson(branchesText, out, error);
|
||||
if (error.empty())
|
||||
if (error.empty()) {
|
||||
return !out.empty();
|
||||
}
|
||||
|
||||
fail:
|
||||
blog(LOG_WARNING, "Loading branches from file failed: %s", error.c_str());
|
||||
@@ -846,8 +872,9 @@ void OBSApp::SetBranchData(const string &data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.empty())
|
||||
if (!result.empty()) {
|
||||
updateBranches = result;
|
||||
}
|
||||
|
||||
branches_loaded = true;
|
||||
#else
|
||||
@@ -864,16 +891,18 @@ std::vector<UpdateBranch> OBSApp::GetBranches()
|
||||
#if defined(_WIN32) || defined(ENABLE_SPARKLE_UPDATER)
|
||||
if (!branches_loaded) {
|
||||
vector<UpdateBranch> result;
|
||||
if (LoadBranchesFile(result))
|
||||
if (LoadBranchesFile(result)) {
|
||||
updateBranches = result;
|
||||
}
|
||||
|
||||
branches_loaded = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copy additional branches to result (if any) */
|
||||
if (!updateBranches.empty())
|
||||
if (!updateBranches.empty()) {
|
||||
out.insert(out.end(), updateBranches.begin(), updateBranches.end());
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -887,8 +916,9 @@ OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
|
||||
|
||||
/* fix float handling */
|
||||
#if defined(Q_OS_UNIX)
|
||||
if (!setlocale(LC_NUMERIC, "C"))
|
||||
if (!setlocale(LC_NUMERIC, "C")) {
|
||||
blog(LOG_WARNING, "Failed to set LC_NUMERIC to C locale");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -1050,14 +1080,18 @@ void OBSApp::AppInit()
|
||||
|
||||
QAccessible::installFactory(alignmentSelectorFactory);
|
||||
|
||||
if (!MakeUserDirs())
|
||||
if (!MakeUserDirs()) {
|
||||
throw "Failed to create required user directories";
|
||||
if (!InitGlobalConfig())
|
||||
}
|
||||
if (!InitGlobalConfig()) {
|
||||
throw "Failed to initialize global config";
|
||||
if (!InitLocale())
|
||||
}
|
||||
if (!InitLocale()) {
|
||||
throw "Failed to load locale";
|
||||
if (!InitTheme())
|
||||
}
|
||||
if (!InitTheme()) {
|
||||
throw "Failed to load theme";
|
||||
}
|
||||
|
||||
config_set_default_string(userConfig, "Basic", "Profile", Str("Untitled"));
|
||||
config_set_default_string(userConfig, "Basic", "ProfileDir", Str("Untitled"));
|
||||
@@ -1081,13 +1115,15 @@ void OBSApp::AppInit()
|
||||
|
||||
#ifdef _WIN32
|
||||
bool disableAudioDucking = config_get_bool(appConfig, "Audio", "DisableAudioDucking");
|
||||
if (disableAudioDucking)
|
||||
if (disableAudioDucking) {
|
||||
DisableAudioDucking(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (config_get_bool(appConfig, "Video", "DisableOSXVSync"))
|
||||
if (config_get_bool(appConfig, "Video", "DisableOSXVSync")) {
|
||||
EnableOSXVSync(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
UpdateHotkeyFocusSetting(false);
|
||||
@@ -1095,9 +1131,10 @@ void OBSApp::AppInit()
|
||||
move_basic_to_profiles();
|
||||
move_basic_to_scene_collections();
|
||||
|
||||
if (!MakeUserProfileDirs())
|
||||
if (!MakeUserProfileDirs()) {
|
||||
throw "Failed to create profile directories";
|
||||
}
|
||||
}
|
||||
|
||||
void OBSApp::checkForUncleanShutdown()
|
||||
{
|
||||
@@ -1134,8 +1171,9 @@ static bool StartupOBS(const char *locale, profiler_name_store_t *store)
|
||||
{
|
||||
char path[512];
|
||||
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/plugin_config") <= 0)
|
||||
if (GetAppConfigPath(path, sizeof(path), "obs-studio/plugin_config") <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return obs_startup(locale, path, store);
|
||||
}
|
||||
@@ -1158,9 +1196,10 @@ void OBSApp::UpdateHotkeyFocusSetting(bool resetState)
|
||||
enableHotkeysOutOfFocus = false;
|
||||
}
|
||||
|
||||
if (resetState)
|
||||
if (resetState) {
|
||||
ResetHotkeyState(applicationState() == Qt::ApplicationActive);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSApp::DisableHotkeys()
|
||||
{
|
||||
@@ -1227,8 +1266,9 @@ bool OBSApp::OBSInit()
|
||||
setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
#endif
|
||||
|
||||
if (!StartupOBS(locale.c_str(), GetProfilerNameStore()))
|
||||
if (!StartupOBS(locale.c_str(), GetProfilerNameStore())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
libobs_initialized = true;
|
||||
|
||||
@@ -1296,10 +1336,11 @@ string OBSApp::GetVersionString(bool platform) const
|
||||
if (platform) {
|
||||
ver << " (";
|
||||
#ifdef _WIN32
|
||||
if (sizeof(void *) == 8)
|
||||
if (sizeof(void *) == 8) {
|
||||
ver << "64-bit, ";
|
||||
else
|
||||
} else {
|
||||
ver << "32-bit, ";
|
||||
}
|
||||
|
||||
ver << "windows)";
|
||||
#elif __APPLE__
|
||||
@@ -1414,9 +1455,10 @@ OBS::LogFileState OBSApp::getLogFileState(OBS::LogFileType type) const
|
||||
bool OBSApp::TranslateString(const char *lookupVal, const char **out) const
|
||||
{
|
||||
for (obs_frontend_translate_ui_cb cb : translatorHooks) {
|
||||
if (cb(lookupVal, out))
|
||||
if (cb(lookupVal, out)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return text_lookup_getstr(App()->GetTextLookup(), lookupVal, out);
|
||||
}
|
||||
@@ -1438,29 +1480,34 @@ bool OBSApp::notify(QObject *receiver, QEvent *e)
|
||||
QWindow *window;
|
||||
int windowType;
|
||||
|
||||
if (!receiver->isWidgetType())
|
||||
if (!receiver->isWidgetType()) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if (e->type() != QEvent::Show)
|
||||
if (e->type() != QEvent::Show) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
w = qobject_cast<QWidget *>(receiver);
|
||||
|
||||
if (!w->isWindow())
|
||||
if (!w->isWindow()) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
window = w->windowHandle();
|
||||
if (!window)
|
||||
if (!window) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
windowType = window->flags() & Qt::WindowType::WindowType_Mask;
|
||||
|
||||
if (windowType == Qt::WindowType::Dialog || windowType == Qt::WindowType::Window ||
|
||||
windowType == Qt::WindowType::Tool) {
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
if (main)
|
||||
if (main) {
|
||||
main->SetDisplayAffinity(window);
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
return QApplication::notify(receiver, e);
|
||||
@@ -1490,12 +1537,14 @@ static void FindBestFilename(string &strPath, bool noSpace)
|
||||
{
|
||||
int num = 2;
|
||||
|
||||
if (!os_file_exists(strPath.c_str()))
|
||||
if (!os_file_exists(strPath.c_str())) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *ext = strrchr(strPath.c_str(), '.');
|
||||
if (!ext)
|
||||
if (!ext) {
|
||||
return;
|
||||
}
|
||||
|
||||
int extStart = int(ext - strPath.c_str());
|
||||
for (;;) {
|
||||
@@ -1504,8 +1553,9 @@ static void FindBestFilename(string &strPath, bool noSpace)
|
||||
|
||||
numStr = noSpace ? "_" : " (";
|
||||
numStr += to_string(num++);
|
||||
if (!noSpace)
|
||||
if (!noSpace) {
|
||||
numStr += ")";
|
||||
}
|
||||
|
||||
testPath.insert(extStart, numStr);
|
||||
|
||||
@@ -1521,8 +1571,9 @@ static void ensure_directory_exists(string &path)
|
||||
replace(path.begin(), path.end(), '\\', '/');
|
||||
|
||||
size_t last = path.rfind('/');
|
||||
if (last == string::npos)
|
||||
if (last == string::npos) {
|
||||
return;
|
||||
}
|
||||
|
||||
string directory = path.substr(0, last);
|
||||
os_mkdirs(directory.c_str());
|
||||
@@ -1549,26 +1600,30 @@ string GetFormatString(const char *format, const char *prefix, const char *suffi
|
||||
if (prefix && *prefix) {
|
||||
string str_prefix = prefix;
|
||||
|
||||
if (str_prefix.back() != ' ')
|
||||
if (str_prefix.back() != ' ') {
|
||||
str_prefix += " ";
|
||||
}
|
||||
|
||||
size_t insert_pos = 0;
|
||||
size_t tmp;
|
||||
|
||||
tmp = f.find_last_of('/');
|
||||
if (tmp != string::npos && tmp > insert_pos)
|
||||
if (tmp != string::npos && tmp > insert_pos) {
|
||||
insert_pos = tmp + 1;
|
||||
}
|
||||
|
||||
tmp = f.find_last_of('\\');
|
||||
if (tmp != string::npos && tmp > insert_pos)
|
||||
if (tmp != string::npos && tmp > insert_pos) {
|
||||
insert_pos = tmp + 1;
|
||||
}
|
||||
|
||||
f.insert(insert_pos, str_prefix);
|
||||
}
|
||||
|
||||
if (suffix && *suffix) {
|
||||
if (*suffix != ' ')
|
||||
if (*suffix != ' ') {
|
||||
f += " ";
|
||||
}
|
||||
f += suffix;
|
||||
}
|
||||
|
||||
@@ -1580,14 +1635,15 @@ string GetFormatString(const char *format, const char *prefix, const char *suffi
|
||||
string GetFormatExt(const char *container)
|
||||
{
|
||||
string ext = container;
|
||||
if (ext == "fragmented_mp4" || ext == "hybrid_mp4")
|
||||
if (ext == "fragmented_mp4" || ext == "hybrid_mp4") {
|
||||
ext = "mp4";
|
||||
else if (ext == "fragmented_mov" || ext == "hybrid_mov")
|
||||
} else if (ext == "fragmented_mov" || ext == "hybrid_mov") {
|
||||
ext = "mov";
|
||||
else if (ext == "hls")
|
||||
} else if (ext == "hls") {
|
||||
ext = "m3u8";
|
||||
else if (ext == "mpegts")
|
||||
} else if (ext == "mpegts") {
|
||||
ext = "ts";
|
||||
}
|
||||
|
||||
return ext;
|
||||
}
|
||||
@@ -1599,10 +1655,11 @@ string GetOutputFilename(const char *path, const char *container, bool noSpace,
|
||||
os_dir_t *dir = path && path[0] ? os_opendir(path) : nullptr;
|
||||
|
||||
if (!dir) {
|
||||
if (main->isVisible())
|
||||
if (main->isVisible()) {
|
||||
OBSMessageBox::warning(main, QTStr("Output.BadPath.Title"), QTStr("Output.BadPath.Text"));
|
||||
else
|
||||
} else {
|
||||
main->SysTrayNotify(QTStr("Output.BadPath.Text"), QSystemTrayIcon::Warning);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -1612,14 +1669,16 @@ string GetOutputFilename(const char *path, const char *container, bool noSpace,
|
||||
strPath += path;
|
||||
|
||||
char lastChar = strPath.back();
|
||||
if (lastChar != '/' && lastChar != '\\')
|
||||
if (lastChar != '/' && lastChar != '\\') {
|
||||
strPath += "/";
|
||||
}
|
||||
|
||||
string ext = GetFormatExt(container);
|
||||
strPath += GenerateSpecifiedFilename(ext.c_str(), noSpace, format);
|
||||
ensure_directory_exists(strPath);
|
||||
if (!overwrite)
|
||||
if (!overwrite) {
|
||||
FindBestFilename(strPath, noSpace);
|
||||
}
|
||||
|
||||
return strPath;
|
||||
}
|
||||
@@ -1627,12 +1686,14 @@ string GetOutputFilename(const char *path, const char *container, bool noSpace,
|
||||
vector<pair<string, string>> GetLocaleNames()
|
||||
{
|
||||
string path;
|
||||
if (!GetDataFilePath("locale.ini", path))
|
||||
if (!GetDataFilePath("locale.ini", path)) {
|
||||
throw "Could not find locale.ini path";
|
||||
}
|
||||
|
||||
ConfigFile ini;
|
||||
if (ini.Open(path.c_str(), CONFIG_OPEN_EXISTING) != 0)
|
||||
if (ini.Open(path.c_str(), CONFIG_OPEN_EXISTING) != 0) {
|
||||
throw "Could not open locale.ini";
|
||||
}
|
||||
|
||||
size_t sections = config_num_sections(ini);
|
||||
|
||||
@@ -1713,8 +1774,9 @@ bool GetFileSafeName(const char *name, std::string &file)
|
||||
size_t len = os_utf8_to_wcs(name, base_len, nullptr, 0);
|
||||
std::wstring wfile;
|
||||
|
||||
if (!len)
|
||||
if (!len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wfile.resize(len);
|
||||
os_utf8_to_wcs(name, base_len, &wfile[0], len + 1);
|
||||
@@ -1729,12 +1791,14 @@ bool GetFileSafeName(const char *name, std::string &file)
|
||||
}
|
||||
}
|
||||
|
||||
if (wfile.size() == 0)
|
||||
if (wfile.size() == 0) {
|
||||
wfile = L"characters_only";
|
||||
}
|
||||
|
||||
len = os_wcs_to_utf8(wfile.c_str(), wfile.size(), nullptr, 0);
|
||||
if (!len)
|
||||
if (!len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
file.resize(len);
|
||||
os_wcs_to_utf8(wfile.c_str(), wfile.size(), &file[0], len + 1);
|
||||
@@ -1749,8 +1813,9 @@ bool GetClosestUnusedFileName(std::string &path, const char *extension)
|
||||
path += extension;
|
||||
}
|
||||
|
||||
if (!os_file_exists(path.c_str()))
|
||||
if (!os_file_exists(path.c_str())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int index = 1;
|
||||
|
||||
@@ -1769,9 +1834,10 @@ bool GetClosestUnusedFileName(std::string &path, const char *extension)
|
||||
bool WindowPositionValid(QRect rect)
|
||||
{
|
||||
for (QScreen *screen : QGuiApplication::screens()) {
|
||||
if (screen->availableGeometry().intersects(rect))
|
||||
if (screen->availableGeometry().intersects(rect)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1930,8 +1996,9 @@ void OBSApp::applicationShutdown() noexcept
|
||||
{
|
||||
#ifdef _WIN32
|
||||
bool disableAudioDucking = config_get_bool(appConfig, "Audio", "DisableAudioDucking");
|
||||
if (disableAudioDucking)
|
||||
if (disableAudioDucking) {
|
||||
DisableAudioDucking(false);
|
||||
}
|
||||
#else
|
||||
auto disconnectSignal = [this](std::array<int, 2> &fileDescriptor,
|
||||
QPointer<QSocketNotifier> ¬ifier) -> void {
|
||||
@@ -1951,8 +2018,9 @@ void OBSApp::applicationShutdown() noexcept
|
||||
#ifdef __APPLE__
|
||||
bool vsyncDisabled = config_get_bool(appConfig, "Video", "DisableOSXVSync");
|
||||
bool resetVSync = config_get_bool(appConfig, "Video", "ResetOSXVSyncOnExit");
|
||||
if (vsyncDisabled && resetVSync)
|
||||
if (vsyncDisabled && resetVSync) {
|
||||
EnableOSXVSync(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
os_inhibit_sleep_set_active(sleepInhibitor, false);
|
||||
|
||||
+10
-5
@@ -205,21 +205,26 @@ public:
|
||||
|
||||
inline void IncrementSleepInhibition()
|
||||
{
|
||||
if (!sleepInhibitor)
|
||||
if (!sleepInhibitor) {
|
||||
return;
|
||||
if (sleepInhibitRefs++ == 0)
|
||||
}
|
||||
if (sleepInhibitRefs++ == 0) {
|
||||
os_inhibit_sleep_set_active(sleepInhibitor, true);
|
||||
}
|
||||
}
|
||||
|
||||
inline void DecrementSleepInhibition()
|
||||
{
|
||||
if (!sleepInhibitor)
|
||||
if (!sleepInhibitor) {
|
||||
return;
|
||||
if (sleepInhibitRefs == 0)
|
||||
}
|
||||
if (sleepInhibitRefs == 0) {
|
||||
return;
|
||||
if (--sleepInhibitRefs == 0)
|
||||
}
|
||||
if (--sleepInhibitRefs == 0) {
|
||||
os_inhibit_sleep_set_active(sleepInhibitor, false);
|
||||
}
|
||||
}
|
||||
|
||||
inline void PushUITranslation(obs_frontend_translate_ui_cb cb) { translatorHooks.emplace_front(cb); }
|
||||
|
||||
|
||||
+158
-90
@@ -46,16 +46,18 @@ struct CFParser {
|
||||
static optional<OBSTheme> ParseThemeMeta(const QString &path)
|
||||
{
|
||||
QFile themeFile(path);
|
||||
if (!themeFile.open(QIODeviceBase::ReadOnly))
|
||||
if (!themeFile.open(QIODeviceBase::ReadOnly)) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
OBSTheme meta;
|
||||
const QByteArray data = themeFile.readAll();
|
||||
CFParser cfp;
|
||||
int ret;
|
||||
|
||||
if (!cf_parser_parse(cfp, data.constData(), QT_TO_UTF8(path)))
|
||||
if (!cf_parser_parse(cfp, data.constData(), QT_TO_UTF8(path))) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
if (cf_token_is(cfp, "@") || cf_go_to_token(cfp, "@", nullptr)) {
|
||||
while (cf_next_token(cfp)) {
|
||||
@@ -63,60 +65,71 @@ static optional<OBSTheme> ParseThemeMeta(const QString &path)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cf_go_to_token(cfp, "@", nullptr))
|
||||
if (!cf_go_to_token(cfp, "@", nullptr)) {
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "OBSThemeMeta")) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "OBSThemeMeta"))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
return nullopt;
|
||||
|
||||
if (!cf_token_is(cfp, "{"))
|
||||
if (!cf_token_is(cfp, "{")) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_NAME, "name", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
string name(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ":", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_STRING, "value", ";");
|
||||
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BPtr str = cf_literal_to_str(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
|
||||
if (str) {
|
||||
if (name == "dark")
|
||||
if (name == "dark") {
|
||||
meta.isDark = strcmp(str, "true") == 0;
|
||||
else if (name == "extends")
|
||||
} else if (name == "extends") {
|
||||
meta.extends = str;
|
||||
else if (name == "author")
|
||||
} else if (name == "author") {
|
||||
meta.author = str;
|
||||
else if (name == "id")
|
||||
} else if (name == "id") {
|
||||
meta.id = str;
|
||||
else if (name == "name")
|
||||
} else if (name == "name") {
|
||||
meta.name = str;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cf_go_to_token(cfp, ";", nullptr))
|
||||
if (!cf_go_to_token(cfp, ";", nullptr)) {
|
||||
return nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto filepath = filesystem::u8path(path.toStdString());
|
||||
meta.isBaseTheme = filepath.extension() == ".obt";
|
||||
@@ -139,22 +152,27 @@ static bool ParseVarName(CFParser &cfp, QString &value)
|
||||
int ret;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, "(", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
ret = cf_next_token_should_be(cfp, "-", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
ret = cf_next_token_should_be(cfp, "-", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
return false;
|
||||
if (!cf_next_token(cfp))
|
||||
}
|
||||
if (!cf_next_token(cfp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = QString::fromUtf8(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ")", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !value.isEmpty();
|
||||
}
|
||||
@@ -166,35 +184,40 @@ static QColor ParseColor(CFParser &cfp)
|
||||
QColor res(QColor::Invalid);
|
||||
|
||||
if (cf_token_is(cfp, "#")) {
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
color = strtol(cfp->cur_token->str.array, nullptr, 16);
|
||||
} else if (cf_token_is(cfp, "rgb")) {
|
||||
int ret = cf_next_token_should_be(cfp, "(", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS || !cf_next_token(cfp))
|
||||
if (ret != PARSE_SUCCESS || !cf_next_token(cfp)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10) << 16;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ",", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS || !cf_next_token(cfp))
|
||||
if (ret != PARSE_SUCCESS || !cf_next_token(cfp)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10) << 8;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ",", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS || !cf_next_token(cfp))
|
||||
if (ret != PARSE_SUCCESS || !cf_next_token(cfp)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ")", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
} else if (cf_token_is(cfp, "bikeshed")) {
|
||||
color |= QRandomGenerator::global()->bounded(INT8_MAX) << 16;
|
||||
color |= QRandomGenerator::global()->bounded(INT8_MAX) << 8;
|
||||
@@ -208,14 +231,17 @@ static QColor ParseColor(CFParser &cfp)
|
||||
static bool ParseMath(CFParser &cfp, QStringList &values, vector<OBSThemeVariable> &vars)
|
||||
{
|
||||
int ret = cf_next_token_should_be(cfp, "(", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
return false;
|
||||
if (!cf_next_token(cfp))
|
||||
}
|
||||
if (!cf_next_token(cfp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!cf_token_is(cfp, ")")) {
|
||||
if (cf_token_is(cfp, ";"))
|
||||
if (cf_token_is(cfp, ";")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cf_token_is(cfp, "calc") || cf_token_is(cfp, "max") || cf_token_is(cfp, "min")) {
|
||||
/* Internal math operations do not have proper names.
|
||||
@@ -226,15 +252,17 @@ static bool ParseMath(CFParser &cfp, QStringList &values, vector<OBSThemeVariabl
|
||||
var.name = QString("__unnamed_%1").arg(QRandomGenerator::global()->generate64());
|
||||
|
||||
OBSThemeVariable::VariableType varType;
|
||||
if (cf_token_is(cfp, "calc"))
|
||||
if (cf_token_is(cfp, "calc")) {
|
||||
varType = OBSThemeVariable::Calc;
|
||||
else if (cf_token_is(cfp, "max"))
|
||||
} else if (cf_token_is(cfp, "max")) {
|
||||
varType = OBSThemeVariable::Max;
|
||||
else if (cf_token_is(cfp, "min"))
|
||||
} else if (cf_token_is(cfp, "min")) {
|
||||
varType = OBSThemeVariable::Min;
|
||||
}
|
||||
|
||||
if (!ParseMath(cfp, subvalues, vars))
|
||||
if (!ParseMath(cfp, subvalues, vars)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var.type = varType;
|
||||
var.value = subvalues;
|
||||
@@ -242,17 +270,19 @@ static bool ParseMath(CFParser &cfp, QStringList &values, vector<OBSThemeVariabl
|
||||
vars.push_back(std::move(var));
|
||||
} else if (cf_token_is(cfp, "var")) {
|
||||
QString value;
|
||||
if (!ParseVarName(cfp, value))
|
||||
if (!ParseVarName(cfp, value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
values << value;
|
||||
} else {
|
||||
values << QString::fromUtf8(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !values.isEmpty();
|
||||
}
|
||||
@@ -264,43 +294,54 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
||||
|
||||
std::vector<OBSThemeVariable> vars;
|
||||
|
||||
if (!cf_parser_parse(cfp, themeData, nullptr))
|
||||
return vars;
|
||||
|
||||
if (!cf_token_is(cfp, "@") && !cf_go_to_token(cfp, "@", nullptr))
|
||||
return vars;
|
||||
|
||||
while (cf_next_token(cfp)) {
|
||||
if (cf_token_is(cfp, "OBSThemeVars"))
|
||||
break;
|
||||
|
||||
if (!cf_go_to_token(cfp, "@", nullptr))
|
||||
if (!cf_parser_parse(cfp, themeData, nullptr)) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
return {};
|
||||
if (!cf_token_is(cfp, "@") && !cf_go_to_token(cfp, "@", nullptr)) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "{"))
|
||||
while (cf_next_token(cfp)) {
|
||||
if (cf_token_is(cfp, "OBSThemeVars")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cf_go_to_token(cfp, "@", nullptr)) {
|
||||
return vars;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "{")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "-"))
|
||||
if (!cf_token_is(cfp, "-")) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
ret = cf_next_token_should_be(cfp, "-", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_NAME, "key", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
QString key = QString::fromUtf8(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
OBSThemeVariable var;
|
||||
@@ -319,16 +360,19 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
||||
}
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ":", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
if (ret != PARSE_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
/* Special values passed to the theme by OBS are prefixed with 'obs', so we
|
||||
* prevent theme variables from using it as a prefix. */
|
||||
if (key.startsWith("obs"))
|
||||
if (key.startsWith("obs")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cfp->cur_token->type == CFTOKEN_NUM) {
|
||||
const char *ch = cfp->cur_token->str.array;
|
||||
@@ -349,31 +393,35 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
||||
}
|
||||
} else if (cf_token_is(cfp, "rgb") || cf_token_is(cfp, "#") || cf_token_is(cfp, "bikeshed")) {
|
||||
QColor color = ParseColor(cfp);
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var.value = color;
|
||||
var.type = OBSThemeVariable::Color;
|
||||
} else if (cf_token_is(cfp, "var")) {
|
||||
QString value;
|
||||
|
||||
if (!ParseVarName(cfp, value))
|
||||
if (!ParseVarName(cfp, value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var.value = value;
|
||||
var.type = OBSThemeVariable::Alias;
|
||||
} else if (cf_token_is(cfp, "calc") || cf_token_is(cfp, "max") || cf_token_is(cfp, "min")) {
|
||||
QStringList values;
|
||||
|
||||
if (cf_token_is(cfp, "calc"))
|
||||
if (cf_token_is(cfp, "calc")) {
|
||||
var.type = OBSThemeVariable::Calc;
|
||||
else if (cf_token_is(cfp, "max"))
|
||||
} else if (cf_token_is(cfp, "max")) {
|
||||
var.type = OBSThemeVariable::Max;
|
||||
else if (cf_token_is(cfp, "min"))
|
||||
} else if (cf_token_is(cfp, "min")) {
|
||||
var.type = OBSThemeVariable::Min;
|
||||
}
|
||||
|
||||
if (!ParseMath(cfp, values, vars))
|
||||
if (!ParseMath(cfp, values, vars)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var.value = values;
|
||||
} else {
|
||||
@@ -382,8 +430,9 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
||||
var.value = QString::fromUtf8(strVal.Get());
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
if (!cf_next_token(cfp)) {
|
||||
return vars;
|
||||
}
|
||||
|
||||
if (cf_token_is(cfp, "!") &&
|
||||
cf_next_token_should_be(cfp, "editable", nullptr, nullptr) == PARSE_SUCCESS) {
|
||||
@@ -398,9 +447,10 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
||||
|
||||
vars.push_back(std::move(var));
|
||||
|
||||
if (!cf_token_is(cfp, ";") && !cf_go_to_token(cfp, ";", nullptr))
|
||||
if (!cf_token_is(cfp, ";") && !cf_go_to_token(cfp, ";", nullptr)) {
|
||||
return vars;
|
||||
}
|
||||
}
|
||||
|
||||
return vars;
|
||||
}
|
||||
@@ -420,10 +470,11 @@ void OBSApp::FindThemes()
|
||||
QDirIterator it(QString::fromStdString(themeDir), filters, QDir::Files);
|
||||
while (it.hasNext()) {
|
||||
auto theme = ParseThemeMeta(it.next());
|
||||
if (theme && !themes.contains(theme->id))
|
||||
if (theme && !themes.contains(theme->id)) {
|
||||
themes[theme->id] = std::move(*theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const std::string themeDir = App()->userConfigLocation.u8string() + "/obs-studio/themes";
|
||||
@@ -432,10 +483,11 @@ void OBSApp::FindThemes()
|
||||
|
||||
while (it.hasNext()) {
|
||||
auto theme = ParseThemeMeta(it.next());
|
||||
if (theme && !themes.contains(theme->id))
|
||||
if (theme && !themes.contains(theme->id)) {
|
||||
themes[theme->id] = std::move(*theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build dependency tree for all themes, removing ones that have items missing. */
|
||||
QSet<QString> invalid;
|
||||
@@ -476,8 +528,9 @@ void OBSApp::FindThemes()
|
||||
}
|
||||
|
||||
/* Mark this theme as a variant of first parent that is a base theme. */
|
||||
if (!theme.isBaseTheme && parent->isBaseTheme && theme.parent.isEmpty())
|
||||
if (!theme.isBaseTheme && parent->isBaseTheme && theme.parent.isEmpty()) {
|
||||
theme.parent = parent->id;
|
||||
}
|
||||
|
||||
theme.dependencies.push_front(parent->id);
|
||||
parentId = parent->extends;
|
||||
@@ -498,8 +551,9 @@ void OBSApp::FindThemes()
|
||||
|
||||
static bool ResolveVariable(const QHash<QString, OBSThemeVariable> &vars, OBSThemeVariable &var)
|
||||
{
|
||||
if (var.type != OBSThemeVariable::Alias)
|
||||
if (var.type != OBSThemeVariable::Alias) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString key = var.value.toString();
|
||||
while (vars[key].type == OBSThemeVariable::Alias) {
|
||||
@@ -627,14 +681,15 @@ static QString EvalMath(const QHash<QString, OBSThemeVariable> &vars, const OBST
|
||||
double val = numeric_limits<double>::quiet_NaN();
|
||||
|
||||
if (type == OBSThemeVariable::Calc) {
|
||||
if (opt == "+")
|
||||
if (opt == "+") {
|
||||
val = d1 + d2;
|
||||
else if (opt == "-")
|
||||
} else if (opt == "-") {
|
||||
val = d1 - d2;
|
||||
else if (opt == "*")
|
||||
} else if (opt == "*") {
|
||||
val = d1 * d2;
|
||||
else if (opt == "/")
|
||||
} else if (opt == "/") {
|
||||
val = d1 / d2;
|
||||
}
|
||||
|
||||
if (!isnormal(val)) {
|
||||
blog(LOG_ERROR, "Invalid calc() resulted in non-normal number: %f %s %f = %f", d1,
|
||||
@@ -651,10 +706,11 @@ static QString EvalMath(const QHash<QString, OBSThemeVariable> &vars, const OBST
|
||||
QString result = QString::number(val, 'f', isInteger ? 0 : -1);
|
||||
|
||||
/* Carry-over suffix */
|
||||
if (!val1.suffix.isEmpty())
|
||||
if (!val1.suffix.isEmpty()) {
|
||||
result += val1.suffix;
|
||||
else if (!val2.suffix.isEmpty())
|
||||
} else if (!val2.suffix.isEmpty()) {
|
||||
result += val2.suffix;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -690,8 +746,9 @@ static QString PrepareQSS(const QHash<QString, OBSThemeVariable> &vars, const QS
|
||||
for (const OBSThemeVariable &var_ : vars) {
|
||||
OBSThemeVariable var(var_);
|
||||
|
||||
if (!ResolveVariable(vars, var))
|
||||
if (!ResolveVariable(vars, var)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString needle = needleTemplate.arg(var_.name);
|
||||
QString replace;
|
||||
@@ -709,8 +766,9 @@ static QString PrepareQSS(const QHash<QString, OBSThemeVariable> &vars, const QS
|
||||
bool isInteger = ceill(val) == val;
|
||||
replace = QString::number(val, 'f', isInteger ? 0 : -1);
|
||||
|
||||
if (!var.suffix.isEmpty())
|
||||
if (!var.suffix.isEmpty()) {
|
||||
replace += var.suffix;
|
||||
}
|
||||
} else {
|
||||
replace = value.toString();
|
||||
}
|
||||
@@ -747,22 +805,27 @@ static QPalette PreparePalette(const QHash<QString, OBSThemeVariable> &vars, con
|
||||
static QHash<QString, QPalette::ColorRole> roleMap;
|
||||
static QHash<QString, QPalette::ColorGroup> groupMap;
|
||||
|
||||
if (roleMap.empty())
|
||||
if (roleMap.empty()) {
|
||||
FillEnumMap<QPalette::ColorRole>(roleMap);
|
||||
if (groupMap.empty())
|
||||
}
|
||||
if (groupMap.empty()) {
|
||||
FillEnumMap<QPalette::ColorGroup>(groupMap);
|
||||
}
|
||||
|
||||
QPalette pal(defaultPalette);
|
||||
|
||||
for (const OBSThemeVariable &var_ : vars) {
|
||||
if (!var_.name.startsWith("palette_"))
|
||||
if (!var_.name.startsWith("palette_")) {
|
||||
continue;
|
||||
if (var_.name.count("_") < 1 || var_.name.count("_") > 2)
|
||||
}
|
||||
if (var_.name.count("_") < 1 || var_.name.count("_") > 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OBSThemeVariable var(var_);
|
||||
if (!ResolveVariable(vars, var) || var.type != OBSThemeVariable::Color)
|
||||
if (!ResolveVariable(vars, var) || var.type != OBSThemeVariable::Color) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine role and optionally group based on name.
|
||||
* Format is: palette_<role>[_<group>] */
|
||||
@@ -816,8 +879,9 @@ static double getPaddingForDensityId(int id)
|
||||
|
||||
OBSTheme *OBSApp::GetTheme(const QString &name)
|
||||
{
|
||||
if (!themes.contains(name))
|
||||
if (!themes.contains(name)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &themes[name];
|
||||
}
|
||||
@@ -825,8 +889,9 @@ OBSTheme *OBSApp::GetTheme(const QString &name)
|
||||
bool OBSApp::SetTheme(const QString &name)
|
||||
{
|
||||
OBSTheme *theme = GetTheme(name);
|
||||
if (!theme)
|
||||
if (!theme) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (themeWatcher && themeWatcher->files().size() > 0) {
|
||||
themeWatcher->blockSignals(true);
|
||||
@@ -861,10 +926,12 @@ bool OBSApp::SetTheme(const QString &name)
|
||||
/* Find and add high contrast adjustment layer if available */
|
||||
if (HighContrastEnabled()) {
|
||||
for (const OBSTheme &theme_ : themes) {
|
||||
if (!theme_.isHighContrast)
|
||||
if (!theme_.isHighContrast) {
|
||||
continue;
|
||||
if (theme_.parent != theme->id)
|
||||
}
|
||||
if (theme_.parent != theme->id) {
|
||||
continue;
|
||||
}
|
||||
themeIds << theme_.id;
|
||||
break;
|
||||
}
|
||||
@@ -877,8 +944,9 @@ bool OBSApp::SetTheme(const QString &name)
|
||||
QFile file(cur->location);
|
||||
filenames << file.fileName();
|
||||
|
||||
if (!file.open(QIODeviceBase::ReadOnly))
|
||||
if (!file.open(QIODeviceBase::ReadOnly)) {
|
||||
return false;
|
||||
}
|
||||
const QByteArray content = file.readAll();
|
||||
|
||||
for (OBSThemeVariable &var : ParseThemeVariables(content.constData())) {
|
||||
|
||||
+33
-18
@@ -17,9 +17,10 @@ inline size_t GetCallbackIdx(std::vector<OBSStudioCallback<T>> &callbacks, T cal
|
||||
{
|
||||
for (size_t i = 0; i < callbacks.size(); i++) {
|
||||
OBSStudioCallback<T> curCB = callbacks[i];
|
||||
if (curCB.callback == callback && curCB.private_data == private_data)
|
||||
if (curCB.callback == callback && curCB.private_data == private_data) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return (size_t)-1;
|
||||
}
|
||||
@@ -46,10 +47,11 @@ void OBSStudioAPI::obs_frontend_get_scenes(struct obs_frontend_source_list *sour
|
||||
OBSScene scene = GetOBSRef<OBSScene>(item);
|
||||
obs_source_t *source = obs_scene_get_source(scene);
|
||||
|
||||
if (obs_source_get_ref(source) != nullptr)
|
||||
if (obs_source_get_ref(source) != nullptr) {
|
||||
da_push_back(sources->sources, &source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *OBSStudioAPI::obs_frontend_get_current_scene()
|
||||
{
|
||||
@@ -77,10 +79,11 @@ void OBSStudioAPI::obs_frontend_get_transitions(struct obs_frontend_source_list
|
||||
for (const auto &[uuid, transition] : main->transitions) {
|
||||
obs_source_t *source = transition;
|
||||
|
||||
if (obs_source_get_ref(source) != nullptr)
|
||||
if (obs_source_get_ref(source) != nullptr) {
|
||||
da_push_back(sources->sources, &source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *OBSStudioAPI::obs_frontend_get_current_transition()
|
||||
{
|
||||
@@ -275,8 +278,9 @@ bool OBSStudioAPI::obs_frontend_recording_split_file()
|
||||
|
||||
bool OBSStudioAPI::obs_frontend_recording_add_chapter(const char *name)
|
||||
{
|
||||
if (!os_atomic_load_bool(&recording_active) || os_atomic_load_bool(&recording_paused))
|
||||
if (!os_atomic_load_bool(&recording_active) || os_atomic_load_bool(&recording_paused)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
proc_handler_t *ph = obs_output_get_proc_handler(main->outputHandler->fileOutput);
|
||||
|
||||
@@ -378,15 +382,17 @@ bool OBSStudioAPI::obs_frontend_add_custom_qdock(const char *id, void *dock)
|
||||
void OBSStudioAPI::obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data)
|
||||
{
|
||||
size_t idx = GetCallbackIdx(callbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
if (idx == (size_t)-1) {
|
||||
callbacks.emplace_back(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSStudioAPI::obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data)
|
||||
{
|
||||
size_t idx = GetCallbackIdx(callbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
if (idx == (size_t)-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
callbacks.erase(callbacks.begin() + idx);
|
||||
}
|
||||
@@ -395,8 +401,9 @@ obs_output_t *OBSStudioAPI::obs_frontend_get_streaming_output()
|
||||
{
|
||||
auto multitrackVideo = main->outputHandler->multitrackVideo.get();
|
||||
auto mtvOutput = multitrackVideo ? obs_output_get_ref(multitrackVideo->StreamingOutput()) : nullptr;
|
||||
if (mtvOutput)
|
||||
if (mtvOutput) {
|
||||
return mtvOutput;
|
||||
}
|
||||
|
||||
OBSOutput output = main->outputHandler->streamOutput.Get();
|
||||
return obs_output_get_ref(output);
|
||||
@@ -438,15 +445,16 @@ void OBSStudioAPI::obs_frontend_open_projector(const char *type, int monitor, co
|
||||
name ? name : "",
|
||||
};
|
||||
if (type) {
|
||||
if (astrcmpi(type, "Source") == 0)
|
||||
if (astrcmpi(type, "Source") == 0) {
|
||||
proj.type = ProjectorType::Source;
|
||||
else if (astrcmpi(type, "Scene") == 0)
|
||||
} else if (astrcmpi(type, "Scene") == 0) {
|
||||
proj.type = ProjectorType::Scene;
|
||||
else if (astrcmpi(type, "StudioProgram") == 0)
|
||||
} else if (astrcmpi(type, "StudioProgram") == 0) {
|
||||
proj.type = ProjectorType::StudioProgram;
|
||||
else if (astrcmpi(type, "Multiview") == 0)
|
||||
} else if (astrcmpi(type, "Multiview") == 0) {
|
||||
proj.type = ProjectorType::Multiview;
|
||||
}
|
||||
}
|
||||
QMetaObject::invokeMethod(main, "OpenSavedProjector", WaitConnection(), Q_ARG(SavedProjectorInfo *, &proj));
|
||||
}
|
||||
|
||||
@@ -468,15 +476,17 @@ void OBSStudioAPI::obs_frontend_defer_save_end()
|
||||
void OBSStudioAPI::obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
size_t idx = GetCallbackIdx(saveCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
if (idx == (size_t)-1) {
|
||||
saveCallbacks.emplace_back(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSStudioAPI::obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
size_t idx = GetCallbackIdx(saveCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
if (idx == (size_t)-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
saveCallbacks.erase(saveCallbacks.begin() + idx);
|
||||
}
|
||||
@@ -484,15 +494,17 @@ void OBSStudioAPI::obs_frontend_remove_save_callback(obs_frontend_save_cb callba
|
||||
void OBSStudioAPI::obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
size_t idx = GetCallbackIdx(preloadCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
if (idx == (size_t)-1) {
|
||||
preloadCallbacks.emplace_back(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSStudioAPI::obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
size_t idx = GetCallbackIdx(preloadCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
if (idx == (size_t)-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
preloadCallbacks.erase(preloadCallbacks.begin() + idx);
|
||||
}
|
||||
@@ -544,9 +556,10 @@ bool OBSStudioAPI::obs_frontend_preview_enabled()
|
||||
|
||||
void OBSStudioAPI::obs_frontend_set_preview_enabled(bool enable)
|
||||
{
|
||||
if (main->previewEnabled != enable)
|
||||
if (main->previewEnabled != enable) {
|
||||
main->EnablePreviewDisplay(enable);
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *OBSStudioAPI::obs_frontend_get_current_preview_scene()
|
||||
{
|
||||
@@ -666,10 +679,11 @@ void OBSStudioAPI::obs_frontend_get_canvases(obs_frontend_canvas_list *canvas_li
|
||||
{
|
||||
for (const auto &canvas : main->canvases) {
|
||||
obs_canvas_t *ref = obs_canvas_get_ref(canvas);
|
||||
if (ref)
|
||||
if (ref) {
|
||||
da_push_back(canvas_list->canvases, &ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obs_canvas_t *OBSStudioAPI::obs_frontend_add_canvas(const char *name, obs_video_info *ovi, int flags)
|
||||
{
|
||||
@@ -731,8 +745,9 @@ void OBSStudioAPI::on_save(obs_data_t *settings)
|
||||
void OBSStudioAPI::on_event(enum obs_frontend_event event)
|
||||
{
|
||||
if (main->disableSaving && event != OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP &&
|
||||
event != OBS_FRONTEND_EVENT_EXIT)
|
||||
event != OBS_FRONTEND_EVENT_EXIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = callbacks.size(); i > 0; i--) {
|
||||
auto cb = callbacks[i - 1];
|
||||
|
||||
@@ -32,11 +32,13 @@ static char **convert_string_list(vector<string> &strings)
|
||||
|
||||
size += string_data_offset;
|
||||
|
||||
for (auto &str : strings)
|
||||
for (auto &str : strings) {
|
||||
size += str.size() + 1;
|
||||
}
|
||||
|
||||
if (!size)
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out = (uint8_t *)bmalloc(size);
|
||||
ptr_list = (char **)out;
|
||||
@@ -73,8 +75,9 @@ void *obs_frontend_get_system_tray(void)
|
||||
|
||||
char **obs_frontend_get_scene_names(void)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
if (!callbacks_valid()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct obs_frontend_source_list sources = {};
|
||||
vector<string> names;
|
||||
@@ -92,9 +95,10 @@ char **obs_frontend_get_scene_names(void)
|
||||
|
||||
void obs_frontend_get_scenes(struct obs_frontend_source_list *sources)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_get_scenes(sources);
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_scene(void)
|
||||
{
|
||||
@@ -103,15 +107,17 @@ obs_source_t *obs_frontend_get_current_scene(void)
|
||||
|
||||
void obs_frontend_set_current_scene(obs_source_t *scene)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_current_scene(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_get_transitions(struct obs_frontend_source_list *sources)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_get_transitions(sources);
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_transition(void)
|
||||
{
|
||||
@@ -120,9 +126,10 @@ obs_source_t *obs_frontend_get_current_transition(void)
|
||||
|
||||
void obs_frontend_set_current_transition(obs_source_t *transition)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_current_transition(transition);
|
||||
}
|
||||
}
|
||||
|
||||
int obs_frontend_get_transition_duration(void)
|
||||
{
|
||||
@@ -131,15 +138,17 @@ int obs_frontend_get_transition_duration(void)
|
||||
|
||||
void obs_frontend_set_transition_duration(int duration)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_transition_duration(duration);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_release_tbar(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_release_tbar();
|
||||
}
|
||||
}
|
||||
|
||||
int obs_frontend_get_tbar_position(void)
|
||||
{
|
||||
@@ -148,14 +157,16 @@ int obs_frontend_get_tbar_position(void)
|
||||
|
||||
void obs_frontend_set_tbar_position(int position)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_tbar_position(position);
|
||||
}
|
||||
}
|
||||
|
||||
char **obs_frontend_get_scene_collections(void)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
if (!callbacks_valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vector<string> strings;
|
||||
c->obs_frontend_get_scene_collections(strings);
|
||||
@@ -169,9 +180,10 @@ char *obs_frontend_get_current_scene_collection(void)
|
||||
|
||||
void obs_frontend_set_current_scene_collection(const char *collection)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_current_scene_collection(collection);
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_add_scene_collection(const char *name)
|
||||
{
|
||||
@@ -180,8 +192,9 @@ bool obs_frontend_add_scene_collection(const char *name)
|
||||
|
||||
char **obs_frontend_get_profiles(void)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
if (!callbacks_valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vector<string> strings;
|
||||
c->obs_frontend_get_profiles(strings);
|
||||
@@ -200,39 +213,45 @@ char *obs_frontend_get_current_profile_path(void)
|
||||
|
||||
void obs_frontend_set_current_profile(const char *profile)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_current_profile(profile);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_create_profile(const char *name)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_create_profile(name);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_duplicate_profile(const char *name)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_duplicate_profile(name);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_delete_profile(const char *profile)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_delete_profile(profile);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_streaming_start(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_streaming_start();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_streaming_stop(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_streaming_stop();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_streaming_active(void)
|
||||
{
|
||||
@@ -241,15 +260,17 @@ bool obs_frontend_streaming_active(void)
|
||||
|
||||
void obs_frontend_recording_start(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_recording_start();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_recording_stop(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_recording_stop();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_recording_active(void)
|
||||
{
|
||||
@@ -258,9 +279,10 @@ bool obs_frontend_recording_active(void)
|
||||
|
||||
void obs_frontend_recording_pause(bool pause)
|
||||
{
|
||||
if (!!callbacks_valid())
|
||||
if (!!callbacks_valid()) {
|
||||
c->obs_frontend_recording_pause(pause);
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_recording_paused(void)
|
||||
{
|
||||
@@ -279,21 +301,24 @@ bool obs_frontend_recording_add_chapter(const char *name)
|
||||
|
||||
void obs_frontend_replay_buffer_start(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_replay_buffer_start();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_save(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_replay_buffer_save();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_stop(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_replay_buffer_stop();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_replay_buffer_active(void)
|
||||
{
|
||||
@@ -307,9 +332,10 @@ void *obs_frontend_add_tools_menu_qaction(const char *name)
|
||||
|
||||
void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_add_tools_menu_item(name, callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget)
|
||||
{
|
||||
@@ -318,9 +344,10 @@ bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget
|
||||
|
||||
void obs_frontend_remove_dock(const char *id)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_remove_dock(id);
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_add_custom_qdock(const char *id, void *dock)
|
||||
{
|
||||
@@ -329,15 +356,17 @@ bool obs_frontend_add_custom_qdock(const char *id, void *dock)
|
||||
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_add_event_callback(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_remove_event_callback(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_streaming_output(void)
|
||||
{
|
||||
@@ -378,63 +407,73 @@ config_t *obs_frontend_get_global_config(void)
|
||||
|
||||
void obs_frontend_open_projector(const char *type, int monitor, const char *geometry, const char *name)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_open_projector(type, monitor, geometry, name);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_save(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_save();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_defer_save_begin(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_defer_save_begin();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_defer_save_end(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_defer_save_end();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_add_save_callback(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_remove_save_callback(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_add_preload_callback(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_remove_preload_callback(callback, private_data);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_push_ui_translation(translate);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_pop_ui_translation(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_pop_ui_translation();
|
||||
}
|
||||
}
|
||||
|
||||
obs_service_t *obs_frontend_get_streaming_service(void)
|
||||
{
|
||||
@@ -443,15 +482,17 @@ obs_service_t *obs_frontend_get_streaming_service(void)
|
||||
|
||||
void obs_frontend_set_streaming_service(obs_service_t *service)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_streaming_service(service);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_save_streaming_service(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_save_streaming_service();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_preview_program_mode_active(void)
|
||||
{
|
||||
@@ -460,15 +501,17 @@ bool obs_frontend_preview_program_mode_active(void)
|
||||
|
||||
void obs_frontend_set_preview_program_mode(bool enable)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_preview_program_mode(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_preview_program_trigger_transition(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_preview_program_trigger_transition();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_preview_enabled(void)
|
||||
{
|
||||
@@ -477,9 +520,10 @@ bool obs_frontend_preview_enabled(void)
|
||||
|
||||
void obs_frontend_set_preview_enabled(bool enable)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_preview_enabled(enable);
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_preview_scene(void)
|
||||
{
|
||||
@@ -488,21 +532,24 @@ obs_source_t *obs_frontend_get_current_preview_scene(void)
|
||||
|
||||
void obs_frontend_set_current_preview_scene(obs_source_t *scene)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_set_current_preview_scene(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_take_screenshot(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_take_screenshot();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_take_source_screenshot(obs_source_t *source)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_take_source_screenshot(source);
|
||||
}
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_virtualcam_output(void)
|
||||
{
|
||||
@@ -511,15 +558,17 @@ obs_output_t *obs_frontend_get_virtualcam_output(void)
|
||||
|
||||
void obs_frontend_start_virtualcam(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_start_virtualcam();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_stop_virtualcam(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_stop_virtualcam();
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_virtualcam_active(void)
|
||||
{
|
||||
@@ -528,33 +577,38 @@ bool obs_frontend_virtualcam_active(void)
|
||||
|
||||
void obs_frontend_reset_video(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_reset_video();
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_open_source_properties(obs_source_t *source)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_open_source_properties(source);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_open_source_filters(obs_source_t *source)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_open_source_filters(source);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_open_source_interaction(obs_source_t *source)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_open_source_interaction(source);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_open_sceneitem_edit_transform(item);
|
||||
}
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_record_output_path(void)
|
||||
{
|
||||
@@ -589,15 +643,17 @@ char *obs_frontend_get_last_replay(void)
|
||||
void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
|
||||
const char *undo_data, const char *redo_data, bool repeatable)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_add_undo_redo_action(name, undo, redo, undo_data, redo_data, repeatable);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_get_canvases(obs_frontend_canvas_list *canvas_list)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
c->obs_frontend_get_canvases(canvas_list);
|
||||
}
|
||||
}
|
||||
|
||||
obs_canvas_t *obs_frontend_add_canvas(const char *name, obs_video_info *ovi, int flags)
|
||||
{
|
||||
@@ -611,19 +667,22 @@ bool obs_frontend_remove_canvas(obs_canvas_t *canvas)
|
||||
|
||||
void obs_frontend_copy_sceneitem(obs_sceneitem_t *item)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
return c->obs_frontend_copy_sceneitem(item);
|
||||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_can_paste_sceneitem(bool duplicate)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
if (!callbacks_valid()) {
|
||||
return false;
|
||||
}
|
||||
return c->obs_frontend_can_paste_sceneitem(duplicate);
|
||||
}
|
||||
|
||||
void obs_frontend_paste_sceneitem(obs_scene_t *scene, bool duplicate)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
if (callbacks_valid()) {
|
||||
return c->obs_frontend_paste_sceneitem(scene, duplicate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,11 @@ void AbsoluteSlider::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
int val = posToRangeValue(event);
|
||||
|
||||
if (val > maximum())
|
||||
if (val > maximum()) {
|
||||
val = maximum();
|
||||
else if (val < minimum())
|
||||
} else if (val < minimum()) {
|
||||
val = minimum();
|
||||
}
|
||||
|
||||
emit absoluteSliderHovered(val);
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@ void AudioCaptureToolbar::Init()
|
||||
ui->activateButton = nullptr;
|
||||
|
||||
obs_module_t *mod = get_os_module("win-wasapi", "mac-capture", "linux-pulseaudio");
|
||||
if (!mod)
|
||||
if (!mod) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *device_str = get_os_text(mod, "Device", "CoreAudio.Device", "Device");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
@@ -31,8 +31,9 @@ int FillPropertyCombo(QComboBox *c, obs_property_t *p, const std::string &cur_id
|
||||
id = val ? val : "";
|
||||
}
|
||||
|
||||
if (cur_id == id)
|
||||
if (cur_id == id) {
|
||||
cur_idx = (int)i;
|
||||
}
|
||||
|
||||
c->addItem(name, id.c_str());
|
||||
}
|
||||
|
||||
@@ -18,8 +18,9 @@ DeviceCaptureToolbar::DeviceCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
active = obs_data_get_bool(settings, "active");
|
||||
|
||||
obs_module_t *mod = obs_get_module("win-dshow");
|
||||
if (!mod)
|
||||
if (!mod) {
|
||||
return;
|
||||
}
|
||||
|
||||
activateText = obs_module_get_locale_text(mod, "Activate");
|
||||
deactivateText = obs_module_get_locale_text(mod, "Deactivate");
|
||||
|
||||
@@ -21,8 +21,9 @@ void DisplayCaptureToolbar::Init()
|
||||
ui->activateButton = nullptr;
|
||||
|
||||
obs_module_t *mod = get_os_module("win-capture", "mac-capture", "linux-capture");
|
||||
if (!mod)
|
||||
if (!mod) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *device_str = get_os_text(mod, "Monitor", "DisplayCapture.Display", "Screen");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
@@ -18,8 +18,9 @@ void FocusList::dragMoveEvent(QDragMoveEvent *event)
|
||||
QPoint pos = event->position().toPoint();
|
||||
int itemRow = row(itemAt(pos));
|
||||
|
||||
if ((itemRow == currentRow() + 1) || (currentRow() == count() - 1 && itemRow == -1))
|
||||
if ((itemRow == currentRow() + 1) || (currentRow() == count() - 1 && itemRow == -1)) {
|
||||
event->ignore();
|
||||
else
|
||||
} else {
|
||||
QListWidget::dragMoveEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@ GameCaptureToolbar::GameCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
ui->setupUi(this);
|
||||
|
||||
obs_module_t *mod = obs_get_module("win-capture");
|
||||
if (!mod)
|
||||
if (!mod) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui->modeLabel->setText(obs_module_get_locale_text(mod, "Mode"));
|
||||
ui->windowLabel->setText(obs_module_get_locale_text(mod, "WindowCapture.Window"));
|
||||
|
||||
@@ -35,8 +35,9 @@ void ImageSourceToolbar::on_browse_clicked()
|
||||
const char *default_path = obs_property_path_default_path(p);
|
||||
|
||||
QString startDir = ui->path->text();
|
||||
if (startDir.isEmpty())
|
||||
if (startDir.isEmpty()) {
|
||||
startDir = default_path;
|
||||
}
|
||||
|
||||
QString path = OpenFile(this, desc, startDir, filter);
|
||||
if (path.isEmpty()) {
|
||||
|
||||
@@ -180,18 +180,21 @@ void MediaControls::SeekTimerCallback()
|
||||
|
||||
void MediaControls::StartMediaTimer()
|
||||
{
|
||||
if (isSlideshow)
|
||||
if (isSlideshow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mediaTimer.isActive())
|
||||
if (!mediaTimer.isActive()) {
|
||||
mediaTimer.start(16);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaControls::StopMediaTimer()
|
||||
{
|
||||
if (mediaTimer.isActive())
|
||||
if (mediaTimer.isActive()) {
|
||||
mediaTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaControls::SetPlayingState()
|
||||
{
|
||||
@@ -288,11 +291,12 @@ void MediaControls::RefreshControls()
|
||||
break;
|
||||
}
|
||||
|
||||
if (isSlideshow)
|
||||
if (isSlideshow) {
|
||||
UpdateSlideCounter();
|
||||
else
|
||||
} else {
|
||||
SetSliderPosition();
|
||||
}
|
||||
}
|
||||
|
||||
OBSSource MediaControls::GetSource()
|
||||
{
|
||||
@@ -333,10 +337,11 @@ void MediaControls::SetSliderPosition()
|
||||
|
||||
float sliderPosition;
|
||||
|
||||
if (duration)
|
||||
if (duration) {
|
||||
sliderPosition = (time / duration) * (float)ui->slider->maximum();
|
||||
else
|
||||
} else {
|
||||
sliderPosition = 0.0f;
|
||||
}
|
||||
|
||||
ui->slider->setValue((int)sliderPosition);
|
||||
UpdateLabels((int)sliderPosition);
|
||||
@@ -446,16 +451,18 @@ void MediaControls::on_durationLabel_clicked()
|
||||
|
||||
config_set_bool(App()->GetUserConfig(), "BasicWindow", "MediaControlsCountdownTimer", countDownTimer);
|
||||
|
||||
if (MediaPaused())
|
||||
if (MediaPaused()) {
|
||||
SetSliderPosition();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaControls::MoveSliderFoward(int seconds)
|
||||
{
|
||||
OBSSource source = OBSGetStrongRef(weakSource);
|
||||
|
||||
if (!source)
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ms = obs_source_media_get_time(source);
|
||||
ms += seconds * 1000;
|
||||
@@ -468,8 +475,9 @@ void MediaControls::MoveSliderBackwards(int seconds)
|
||||
{
|
||||
OBSSource source = OBSGetStrongRef(weakSource);
|
||||
|
||||
if (!source)
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ms = obs_source_media_get_time(source);
|
||||
ms -= seconds * 1000;
|
||||
@@ -480,13 +488,15 @@ void MediaControls::MoveSliderBackwards(int seconds)
|
||||
|
||||
void MediaControls::UpdateSlideCounter()
|
||||
{
|
||||
if (!isSlideshow)
|
||||
if (!isSlideshow) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSSource source = OBSGetStrongRef(weakSource);
|
||||
|
||||
if (!source)
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
proc_handler_t *ph = obs_source_get_proc_handler(source);
|
||||
calldata_t cd = {};
|
||||
@@ -521,8 +531,9 @@ void MediaControls::UpdateLabels(int val)
|
||||
|
||||
ui->timerLabel->setText(FormatSeconds((int)(time / 1000.0f)));
|
||||
|
||||
if (!countDownTimer)
|
||||
if (!countDownTimer) {
|
||||
ui->durationLabel->setText(FormatSeconds((int)(duration / 1000.0f)));
|
||||
else
|
||||
} else {
|
||||
ui->durationLabel->setText(QString("-") + FormatSeconds((int)((duration - time) / 1000.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ void MenuButton::keyPressEvent(QKeyEvent *event)
|
||||
void MenuButton::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (menu()) {
|
||||
if (width() - event->pos().x() <= 30)
|
||||
if (width() - event->pos().x() <= 30) {
|
||||
showMenu();
|
||||
else
|
||||
} else {
|
||||
setDown(true);
|
||||
}
|
||||
} else {
|
||||
QPushButton::mousePressEvent(event);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@ Multiview::~Multiview()
|
||||
{
|
||||
for (OBSWeakSource &weakSrc : multiviewScenes) {
|
||||
OBSSource src = OBSGetStrongRef(weakSrc);
|
||||
if (src)
|
||||
if (src) {
|
||||
obs_source_dec_showing(src);
|
||||
}
|
||||
}
|
||||
|
||||
obs_enter_graphics();
|
||||
gs_vertexbuffer_destroy(actionSafeMargin);
|
||||
@@ -161,8 +162,9 @@ void Multiview::Update(MultiviewLayout multiviewLayout, bool drawLabel, bool dra
|
||||
OBSDataAutoRelease data = obs_source_get_private_settings(src);
|
||||
|
||||
obs_data_set_default_bool(data, "show_in_multiview", true);
|
||||
if (!obs_data_get_bool(data, "show_in_multiview"))
|
||||
if (!obs_data_get_bool(data, "show_in_multiview")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
updatedScenes.emplace_back(OBSGetWeakRef(src));
|
||||
obs_source_inc_showing(src);
|
||||
@@ -174,9 +176,10 @@ void Multiview::Update(MultiviewLayout multiviewLayout, bool drawLabel, bool dra
|
||||
|
||||
for (OBSWeakSource &weakSrc : multiviewScenes) {
|
||||
OBSSource src = OBSGetStrongRef(weakSrc);
|
||||
if (src)
|
||||
if (src) {
|
||||
obs_source_dec_showing(src);
|
||||
}
|
||||
}
|
||||
|
||||
multiviewScenes = std::move(updatedScenes);
|
||||
multiviewLabels = std::move(updatedLabels);
|
||||
@@ -234,8 +237,9 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
||||
gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
|
||||
|
||||
gs_effect_set_color(color, colorVal);
|
||||
while (gs_effect_loop(solid, "Solid"))
|
||||
while (gs_effect_loop(solid, "Solid")) {
|
||||
gs_draw_sprite(nullptr, 0, (uint32_t)cx, (uint32_t)cy);
|
||||
}
|
||||
};
|
||||
|
||||
auto setRegion = [&](float bx, float by, float cx, float cy) {
|
||||
@@ -265,14 +269,16 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
||||
case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
|
||||
sourceX = pvwprgCX;
|
||||
sourceY = (i / 2) * scenesCY;
|
||||
if (i % 2 != 0)
|
||||
if (i % 2 != 0) {
|
||||
sourceX += scenesCX;
|
||||
}
|
||||
break;
|
||||
case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
|
||||
sourceX = 0;
|
||||
sourceY = (i / 2) * scenesCY;
|
||||
if (i % 2 != 0)
|
||||
if (i % 2 != 0) {
|
||||
sourceX = scenesCX;
|
||||
}
|
||||
break;
|
||||
case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
|
||||
if (i < 4) {
|
||||
@@ -404,10 +410,11 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
||||
|
||||
// We have a source. Now chose the proper highlight color
|
||||
uint32_t colorVal = outerColor;
|
||||
if (src == programSrc)
|
||||
if (src == programSrc) {
|
||||
colorVal = programColor;
|
||||
else if (src == previewSrc)
|
||||
} else if (src == previewSrc) {
|
||||
colorVal = studioMode ? previewColor : programColor;
|
||||
}
|
||||
|
||||
// Paint the background
|
||||
paintAreaWithColor(sourceX, sourceY, scenesCX, scenesCY, colorVal);
|
||||
@@ -427,12 +434,14 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
||||
/* ----------- */
|
||||
|
||||
// Render the label
|
||||
if (!drawLabel)
|
||||
if (!drawLabel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
obs_source *label = multiviewLabels[i + 2];
|
||||
if (!label)
|
||||
if (!label) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = labelOffset(multiviewLayout, label, scenesCX);
|
||||
|
||||
@@ -470,10 +479,11 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
||||
gs_matrix_translate3f(sourceX, sourceY, 0.0f);
|
||||
gs_matrix_scale3f(ppiScaleX, ppiScaleY, 1.0f);
|
||||
setRegion(sourceX, sourceY, ppiCX, ppiCY);
|
||||
if (studioMode)
|
||||
if (studioMode) {
|
||||
obs_source_video_render(previewSrc);
|
||||
else
|
||||
} else {
|
||||
obs_render_main_texture();
|
||||
}
|
||||
|
||||
if (drawSafeArea) {
|
||||
RenderSafeAreas(actionSafeMargin, targetCX, targetCY);
|
||||
@@ -550,8 +560,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
{
|
||||
int pos = -1;
|
||||
QWidget *rec = QApplication::activeWindow();
|
||||
if (!rec)
|
||||
if (!rec) {
|
||||
return nullptr;
|
||||
}
|
||||
int cx = rec->width();
|
||||
int cy = rec->height();
|
||||
int minX = 0;
|
||||
@@ -571,8 +582,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
}
|
||||
minY = cy / 2;
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 6);
|
||||
pos += ((y - minY) / ((maxY - minY) / 3)) * 6;
|
||||
@@ -590,8 +602,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
minY = (cy / 2) - (validY / 6);
|
||||
}
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 6);
|
||||
pos += ((y - minY) / ((maxY - minY) / 4)) * 6;
|
||||
@@ -609,12 +622,14 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
|
||||
minX = cx / 2;
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = 2 * ((y - minY) / ((maxY - minY) / 4));
|
||||
if (x > minX + ((maxX - minX) / 2))
|
||||
if (x > minX + ((maxX - minX) / 2)) {
|
||||
pos++;
|
||||
}
|
||||
break;
|
||||
case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
|
||||
if (float(cx) / float(cy) > ratio) {
|
||||
@@ -628,12 +643,14 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
|
||||
maxX = (cx / 2);
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = 2 * ((y - minY) / ((maxY - minY) / 4));
|
||||
if (x > minX + ((maxX - minX) / 2))
|
||||
if (x > minX + ((maxX - minX) / 2)) {
|
||||
pos++;
|
||||
}
|
||||
break;
|
||||
case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
|
||||
if (float(cx) / float(cy) > ratio) {
|
||||
@@ -647,12 +664,14 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
|
||||
maxY = (cy / 2);
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 4);
|
||||
if (y > minY + ((maxY - minY) / 2))
|
||||
if (y > minY + ((maxY - minY) / 2)) {
|
||||
pos += 4;
|
||||
}
|
||||
break;
|
||||
case MultiviewLayout::SCENES_ONLY_4_SCENES:
|
||||
if (float(cx) / float(cy) > ratio) {
|
||||
@@ -665,8 +684,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
minY = (cy / 2) - (validY / 2);
|
||||
}
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 2);
|
||||
pos += ((y - minY) / ((maxY - minY) / 2)) * 2;
|
||||
@@ -683,8 +703,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
minY = (cy / 2) - (validY / 2);
|
||||
}
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 3);
|
||||
pos += ((y - minY) / ((maxY - minY) / 3)) * 3;
|
||||
@@ -701,8 +722,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
minY = (cy / 2) - (validY / 2);
|
||||
}
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 4);
|
||||
pos += ((y - minY) / ((maxY - minY) / 4)) * 4;
|
||||
@@ -719,8 +741,9 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
minY = (cy / 2) - (validY / 2);
|
||||
}
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
}
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 5);
|
||||
pos += ((y - minY) / ((maxY - minY) / 5)) * 5;
|
||||
@@ -738,16 +761,19 @@ OBSSource Multiview::GetSourceByPosition(int x, int y)
|
||||
|
||||
minY = (cy / 2);
|
||||
|
||||
if (x < minX || x > maxX || y < minY || y > maxY)
|
||||
if (x < minX || x > maxX || y < minY || y > maxY) {
|
||||
break;
|
||||
|
||||
pos = (x - minX) / ((maxX - minX) / 4);
|
||||
if (y > minY + ((maxY - minY) / 2))
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if (pos < 0 || pos >= (int)multiviewScenes.size())
|
||||
pos = (x - minX) / ((maxX - minX) / 4);
|
||||
if (y > minY + ((maxY - minY) / 2)) {
|
||||
pos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos < 0 || pos >= (int)multiviewScenes.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return OBSGetStrongRef(multiviewScenes[pos]);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,10 @@ protected:
|
||||
* able to manually get into the partial state. */
|
||||
void nextCheckState() override
|
||||
{
|
||||
if (checkState() != Qt::Checked)
|
||||
if (checkState() != Qt::Checked) {
|
||||
setCheckState(Qt::Checked);
|
||||
else
|
||||
} else {
|
||||
setCheckState(Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,8 +40,9 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(
|
||||
percent = new QSpinBox();
|
||||
forceMono = new QCheckBox();
|
||||
balance = new BalanceSlider();
|
||||
if (obs_audio_monitoring_available())
|
||||
if (obs_audio_monitoring_available()) {
|
||||
monitoringType = new QComboBox();
|
||||
}
|
||||
syncOffset = new QSpinBox();
|
||||
mixer1 = new QCheckBox();
|
||||
mixer2 = new QCheckBox();
|
||||
@@ -57,8 +58,9 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(
|
||||
sigs.emplace_back(handler, "volume", OBSSourceVolumeChanged, this);
|
||||
sigs.emplace_back(handler, "audio_sync", OBSSourceSyncChanged, this);
|
||||
sigs.emplace_back(handler, "update_flags", OBSSourceFlagsChanged, this);
|
||||
if (obs_audio_monitoring_available())
|
||||
if (obs_audio_monitoring_available()) {
|
||||
sigs.emplace_back(handler, "audio_monitoring", OBSSourceMonitoringTypeChanged, this);
|
||||
}
|
||||
sigs.emplace_back(handler, "audio_mixers", OBSSourceMixersChanged, this);
|
||||
sigs.emplace_back(handler, "audio_balance", OBSSourceBalanceChanged, this);
|
||||
sigs.emplace_back(handler, "rename", OBSSourceRenamed, this);
|
||||
@@ -87,8 +89,9 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(
|
||||
|
||||
bool isActive = obs_source_active(source) && obs_source_audio_active(source);
|
||||
active->setText(isActive ? QTStr("Basic.Stats.Status.Active") : QTStr("Basic.Stats.Status.Inactive"));
|
||||
if (isActive)
|
||||
if (isActive) {
|
||||
setClasses(active, "text-danger");
|
||||
}
|
||||
active->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
|
||||
volume->setMinimum(MIN_DB - 0.1);
|
||||
@@ -132,10 +135,11 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(
|
||||
|
||||
const char *speakers = config_get_string(main->Config(), "Audio", "ChannelSetup");
|
||||
|
||||
if (strcmp(speakers, "Mono") == 0)
|
||||
if (strcmp(speakers, "Mono") == 0) {
|
||||
balance->setEnabled(false);
|
||||
else
|
||||
} else {
|
||||
balance->setEnabled(true);
|
||||
}
|
||||
|
||||
float bal = obs_source_get_balance_value(source) * 100.0f;
|
||||
balance->setValue((int)bal);
|
||||
@@ -187,8 +191,9 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(
|
||||
|
||||
speaker_layout sl = obs_source_get_speaker_layout(source);
|
||||
|
||||
if (sl != SPEAKERS_STEREO)
|
||||
if (sl != SPEAKERS_STEREO) {
|
||||
balanceContainer->setEnabled(false);
|
||||
}
|
||||
|
||||
mixerContainer->layout()->addWidget(mixer1);
|
||||
mixerContainer->layout()->addWidget(mixer2);
|
||||
@@ -204,8 +209,9 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(
|
||||
connect(balance, &BalanceSlider::valueChanged, this, &OBSAdvAudioCtrl::balanceChanged);
|
||||
connect(balance, &BalanceSlider::doubleClicked, this, &OBSAdvAudioCtrl::ResetBalance);
|
||||
connect(syncOffset, &QSpinBox::valueChanged, this, &OBSAdvAudioCtrl::syncOffsetChanged);
|
||||
if (obs_audio_monitoring_available())
|
||||
if (obs_audio_monitoring_available()) {
|
||||
connect(monitoringType, &QComboBox::currentIndexChanged, this, &OBSAdvAudioCtrl::monitoringTypeChanged);
|
||||
}
|
||||
|
||||
auto connectMixer = [this](QCheckBox *mixer, int num) {
|
||||
connect(mixer, &QCheckBox::clicked, this,
|
||||
@@ -230,8 +236,9 @@ OBSAdvAudioCtrl::~OBSAdvAudioCtrl()
|
||||
forceMono->deleteLater();
|
||||
balanceContainer->deleteLater();
|
||||
syncOffset->deleteLater();
|
||||
if (obs_audio_monitoring_available())
|
||||
if (obs_audio_monitoring_available()) {
|
||||
monitoringType->deleteLater();
|
||||
}
|
||||
mixerContainer->deleteLater();
|
||||
}
|
||||
|
||||
@@ -247,8 +254,9 @@ void OBSAdvAudioCtrl::ShowAudioControl(QGridLayout *layout)
|
||||
layout->addWidget(forceMono, lastRow, idx++);
|
||||
layout->addWidget(balanceContainer, lastRow, idx++);
|
||||
layout->addWidget(syncOffset, lastRow, idx++);
|
||||
if (obs_audio_monitoring_available())
|
||||
if (obs_audio_monitoring_available()) {
|
||||
layout->addWidget(monitoringType, lastRow, idx++);
|
||||
}
|
||||
layout->addWidget(mixerContainer, lastRow, idx++);
|
||||
layout->layout()->setAlignment(mixerContainer, Qt::AlignVCenter);
|
||||
layout->setHorizontalSpacing(15);
|
||||
@@ -431,10 +439,11 @@ void OBSAdvAudioCtrl::percentChanged(int percent)
|
||||
static inline void set_mono(obs_source_t *source, bool mono)
|
||||
{
|
||||
uint32_t flags = obs_source_get_flags(source);
|
||||
if (mono)
|
||||
if (mono) {
|
||||
flags |= OBS_SOURCE_FLAG_FORCE_MONO;
|
||||
else
|
||||
} else {
|
||||
flags &= ~OBS_SOURCE_FLAG_FORCE_MONO;
|
||||
}
|
||||
obs_source_set_flags(source, flags);
|
||||
}
|
||||
|
||||
@@ -443,13 +452,15 @@ void OBSAdvAudioCtrl::downmixMonoChanged(bool val)
|
||||
uint32_t flags = obs_source_get_flags(source);
|
||||
bool forceMonoActive = (flags & OBS_SOURCE_FLAG_FORCE_MONO) != 0;
|
||||
|
||||
if (forceMonoActive == val)
|
||||
if (forceMonoActive == val) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (val)
|
||||
if (val) {
|
||||
flags |= OBS_SOURCE_FLAG_FORCE_MONO;
|
||||
else
|
||||
} else {
|
||||
flags &= ~OBS_SOURCE_FLAG_FORCE_MONO;
|
||||
}
|
||||
|
||||
obs_source_set_flags(source, flags);
|
||||
|
||||
@@ -502,8 +513,9 @@ void OBSAdvAudioCtrl::syncOffsetChanged(int milliseconds)
|
||||
int64_t prev = obs_source_get_sync_offset(source);
|
||||
int64_t val = int64_t(milliseconds) * NSEC_PER_MSEC;
|
||||
|
||||
if (prev / NSEC_PER_MSEC == milliseconds)
|
||||
if (prev / NSEC_PER_MSEC == milliseconds) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_source_set_sync_offset(source, val);
|
||||
|
||||
@@ -559,10 +571,11 @@ static inline void setMixer(obs_source_t *source, const int mixerIdx, const bool
|
||||
uint32_t mixers = obs_source_get_audio_mixers(source);
|
||||
uint32_t new_mixers = mixers;
|
||||
|
||||
if (checked)
|
||||
if (checked) {
|
||||
new_mixers |= (1 << mixerIdx);
|
||||
else
|
||||
} else {
|
||||
new_mixers &= ~(1 << mixerIdx);
|
||||
}
|
||||
|
||||
obs_source_set_audio_mixers(source, new_mixers);
|
||||
|
||||
|
||||
@@ -23,8 +23,9 @@
|
||||
|
||||
void OBSPreviewScalingComboBox::PreviewFixedScalingChanged(bool fixed)
|
||||
{
|
||||
if (fixedScaling == fixed)
|
||||
if (fixedScaling == fixed) {
|
||||
return;
|
||||
}
|
||||
|
||||
fixedScaling = fixed;
|
||||
UpdateSelection();
|
||||
@@ -60,8 +61,9 @@ void OBSPreviewScalingComboBox::PreviewScaleChanged(float scale)
|
||||
|
||||
void OBSPreviewScalingComboBox::SetScaleOutputEnabled(bool show)
|
||||
{
|
||||
if (scaleOutputEnabled == show)
|
||||
if (scaleOutputEnabled == show) {
|
||||
return;
|
||||
}
|
||||
|
||||
scaleOutputEnabled = show;
|
||||
|
||||
|
||||
@@ -175,8 +175,9 @@ void SceneTree::RepositionGrid(QDragMoveEvent *event)
|
||||
for (int i = 0; i < count(); i++) {
|
||||
auto *wItem = item(i);
|
||||
|
||||
if (wItem->isSelected())
|
||||
if (wItem->isSelected()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QModelIndex index = indexFromItem(wItem);
|
||||
|
||||
@@ -193,8 +194,9 @@ void SceneTree::RepositionGrid(QDragMoveEvent *event)
|
||||
for (int i = 0; i < count(); i++) {
|
||||
auto *wItem = item(i);
|
||||
|
||||
if (wItem->isSelected())
|
||||
if (wItem->isSelected()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QModelIndex index = indexFromItem(wItem);
|
||||
|
||||
@@ -238,7 +240,8 @@ void SceneTree::rowsInserted(const QModelIndex &parent, int start, int end)
|
||||
// Workaround for QTBUG-105870. Remove once that is solved upstream.
|
||||
void SceneTree::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
if (selected.count() == 0 && deselected.count() > 0 && !property("clearing").toBool())
|
||||
if (selected.count() == 0 && deselected.count() > 0 && !property("clearing").toBool()) {
|
||||
setCurrentRow(deselected.indexes().front().row());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,8 +30,9 @@ void SourceToolbar::SetUndoProperties(obs_source_t *source, bool repeatable)
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
|
||||
OBSSource currentSceneSource = main->GetCurrentSceneSource();
|
||||
if (!currentSceneSource)
|
||||
if (!currentSceneSource) {
|
||||
return;
|
||||
}
|
||||
std::string scene_uuid = obs_source_get_uuid(currentSceneSource);
|
||||
auto undo_redo = [scene_uuid = std::move(scene_uuid), main](const std::string &data) {
|
||||
OBSDataAutoRelease settings = obs_data_create_from_json(data.c_str());
|
||||
@@ -52,9 +53,10 @@ void SourceToolbar::SetUndoProperties(obs_source_t *source, bool repeatable)
|
||||
std::string undo_data(obs_data_get_json(oldData));
|
||||
std::string redo_data(obs_data_get_json(new_settings));
|
||||
|
||||
if (undo_data.compare(redo_data) != 0)
|
||||
if (undo_data.compare(redo_data) != 0) {
|
||||
main->undo_s.add_action(QTStr("Undo.Properties").arg(obs_source_get_name(source)), undo_redo, undo_redo,
|
||||
undo_data, redo_data, repeatable);
|
||||
}
|
||||
|
||||
oldData = nullptr;
|
||||
}
|
||||
|
||||
@@ -95,23 +95,27 @@ void SourceTree::SelectItem(obs_sceneitem_t *sceneitem, bool select)
|
||||
int i = 0;
|
||||
|
||||
for (; i < stm->items.count(); i++) {
|
||||
if (stm->items[i] == sceneitem)
|
||||
if (stm->items[i] == sceneitem) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == stm->items.count())
|
||||
if (i == stm->items.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex index = stm->createIndex(i, 0);
|
||||
if (index.isValid() && select != selectionModel()->isSelected(index))
|
||||
if (index.isValid() && select != selectionModel()->isSelected(index)) {
|
||||
selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTree::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
QListView::mouseDoubleClickEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTree::dropEvent(QDropEvent *event)
|
||||
{
|
||||
@@ -152,10 +156,12 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
obs_sceneitem_t *dropGroup = itemIsGroup ? dropItem : obs_sceneitem_get_group(scene, dropItem);
|
||||
|
||||
/* not a group if moving above the group */
|
||||
if (indicator == QAbstractItemView::AboveItem && itemIsGroup)
|
||||
if (indicator == QAbstractItemView::AboveItem && itemIsGroup) {
|
||||
dropGroup = nullptr;
|
||||
if (emptyDrop)
|
||||
}
|
||||
if (emptyDrop) {
|
||||
dropGroup = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
/* remember to remove list items if */
|
||||
@@ -169,8 +175,9 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
}
|
||||
|
||||
if (indicator == QAbstractItemView::BelowItem || indicator == QAbstractItemView::OnItem ||
|
||||
indicator == QAbstractItemView::OnViewport)
|
||||
indicator == QAbstractItemView::OnViewport) {
|
||||
row++;
|
||||
}
|
||||
|
||||
if (row < 0 || row > stm->items.count()) {
|
||||
QListView::dropEvent(event);
|
||||
@@ -194,10 +201,11 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
/* below another group */
|
||||
|
||||
obs_sceneitem_t *itemBelow;
|
||||
if (row == stm->items.count())
|
||||
if (row == stm->items.count()) {
|
||||
itemBelow = nullptr;
|
||||
else
|
||||
} else {
|
||||
itemBelow = stm->items[row];
|
||||
}
|
||||
|
||||
if (hasGroups) {
|
||||
if (!itemBelow || obs_sceneitem_get_group(scene, itemBelow) != dropGroup) {
|
||||
@@ -220,11 +228,13 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
std::vector<obs_source_t *> sources;
|
||||
for (int i = 0; i < indices.size(); i++) {
|
||||
obs_sceneitem_t *item = items[indices[i].row()];
|
||||
if (obs_sceneitem_get_scene(item) != scene)
|
||||
if (obs_sceneitem_get_scene(item) != scene) {
|
||||
sources.push_back(obs_scene_get_source(obs_sceneitem_get_scene(item)));
|
||||
}
|
||||
if (dropGroup)
|
||||
}
|
||||
if (dropGroup) {
|
||||
sources.push_back(obs_sceneitem_get_source(dropGroup));
|
||||
}
|
||||
OBSData undo_data = main->BackupScene(scene, &sources);
|
||||
|
||||
/* --------------------------------------- */
|
||||
@@ -266,8 +276,9 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
|
||||
QList<QPersistentModelIndex> persistentIndices;
|
||||
persistentIndices.reserve(indices.count());
|
||||
for (QModelIndex &index : indices)
|
||||
for (QModelIndex &index : indices) {
|
||||
persistentIndices.append(index);
|
||||
}
|
||||
std::sort(persistentIndices.begin(), persistentIndices.end());
|
||||
|
||||
/* --------------------------------------- */
|
||||
@@ -279,8 +290,9 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
int to = r;
|
||||
int itemTo = to;
|
||||
|
||||
if (itemTo > from)
|
||||
if (itemTo > from) {
|
||||
itemTo--;
|
||||
}
|
||||
|
||||
if (itemTo != from) {
|
||||
stm->beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
|
||||
@@ -347,10 +359,11 @@ void SourceTree::dropEvent(QDropEvent *event)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hasGroups && i >= firstIdx && i <= lastIdx)
|
||||
if (!hasGroups && i >= firstIdx && i <= lastIdx) {
|
||||
group = dropGroup;
|
||||
else
|
||||
} else {
|
||||
group = obs_sceneitem_get_group(scene, item);
|
||||
}
|
||||
|
||||
if (lastGroup && lastGroup != group) {
|
||||
insertLastGroup();
|
||||
@@ -481,8 +494,9 @@ void SourceTree::NewGroupEdit(int row)
|
||||
bool SourceTree::Edit(int row)
|
||||
{
|
||||
SourceTreeModel *stm = GetStm();
|
||||
if (row < 0 || row >= stm->items.count())
|
||||
if (row < 0 || row >= stm->items.count()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex index = stm->createIndex(row, 0);
|
||||
QWidget *widget = indexWidget(index);
|
||||
|
||||
@@ -9,8 +9,9 @@ QSize SourceTreeDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
|
||||
SourceTree *tree = qobject_cast<SourceTree *>(parent());
|
||||
QWidget *item = tree->indexWidget(index);
|
||||
|
||||
if (!item)
|
||||
if (!item) {
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
return (QSize(item->sizeHint()));
|
||||
}
|
||||
|
||||
@@ -55,12 +55,13 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) : tre
|
||||
if (tree->iconsVisible) {
|
||||
QIcon icon;
|
||||
|
||||
if (strcmp(id, "scene") == 0)
|
||||
if (strcmp(id, "scene") == 0) {
|
||||
icon = main->GetSceneIcon();
|
||||
else if (strcmp(id, "group") == 0)
|
||||
} else if (strcmp(id, "group") == 0) {
|
||||
icon = main->GetGroupIcon();
|
||||
else
|
||||
} else {
|
||||
icon = main->GetSourceIcon(id);
|
||||
}
|
||||
|
||||
QPixmap pixmap = icon.pixmap(QSize(16, 16));
|
||||
|
||||
@@ -136,8 +137,9 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) : tre
|
||||
OBSSourceAutoRelease s = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_scene_t *sc = obs_group_or_scene_from_source(s);
|
||||
obs_sceneitem_t *si = obs_scene_find_sceneitem_by_id(sc, id);
|
||||
if (si)
|
||||
if (si) {
|
||||
obs_sceneitem_set_visible(si, val);
|
||||
}
|
||||
};
|
||||
|
||||
QString str = QTStr(val ? "Undo.ShowSceneItem" : "Undo.HideSceneItem");
|
||||
@@ -183,8 +185,9 @@ void SourceTreeItem::Clear()
|
||||
|
||||
void SourceTreeItem::ReconnectSignals()
|
||||
{
|
||||
if (!sceneitem)
|
||||
if (!sceneitem) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisconnectSignals();
|
||||
|
||||
@@ -200,8 +203,9 @@ void SourceTreeItem::ReconnectSignals()
|
||||
Q_ARG(OBSScene, curScene));
|
||||
curItem = nullptr;
|
||||
}
|
||||
if (!curItem)
|
||||
if (!curItem) {
|
||||
QMetaObject::invokeMethod(this_, "Clear");
|
||||
}
|
||||
};
|
||||
|
||||
auto itemVisible = [](void *data, calldata_t *cd) {
|
||||
@@ -209,8 +213,9 @@ void SourceTreeItem::ReconnectSignals()
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
bool visible = calldata_bool(cd, "visible");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
if (curItem == this_->sceneitem) {
|
||||
QMetaObject::invokeMethod(this_, "VisibilityChanged", Q_ARG(bool, visible));
|
||||
}
|
||||
};
|
||||
|
||||
auto itemLocked = [](void *data, calldata_t *cd) {
|
||||
@@ -218,24 +223,27 @@ void SourceTreeItem::ReconnectSignals()
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
bool locked = calldata_bool(cd, "locked");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
if (curItem == this_->sceneitem) {
|
||||
QMetaObject::invokeMethod(this_, "LockedChanged", Q_ARG(bool, locked));
|
||||
}
|
||||
};
|
||||
|
||||
auto itemSelect = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ = static_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
if (curItem == this_->sceneitem) {
|
||||
QMetaObject::invokeMethod(this_, "Select");
|
||||
}
|
||||
};
|
||||
|
||||
auto itemDeselect = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ = static_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
if (curItem == this_->sceneitem) {
|
||||
QMetaObject::invokeMethod(this_, "Deselect");
|
||||
}
|
||||
};
|
||||
|
||||
auto reorderGroup = [](void *data, calldata_t *) {
|
||||
@@ -384,8 +392,9 @@ void SourceTreeItem::ExitEditModeInternal(bool save)
|
||||
/* ----------------------------------------- */
|
||||
/* check for empty string */
|
||||
|
||||
if (!save)
|
||||
if (!save) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newName.empty()) {
|
||||
OBSMessageBox::information(main, QTStr("NoNameEntered.Title"), QTStr("NoNameEntered.Text"));
|
||||
@@ -396,8 +405,9 @@ void SourceTreeItem::ExitEditModeInternal(bool save)
|
||||
/* Check for same name */
|
||||
|
||||
obs_source_t *source = obs_sceneitem_get_source(sceneitem);
|
||||
if (newName == obs_source_get_name(source))
|
||||
if (newName == obs_source_get_name(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------------- */
|
||||
/* check for existing source */
|
||||
@@ -442,8 +452,9 @@ void SourceTreeItem::ExitEditModeInternal(bool save)
|
||||
|
||||
bool SourceTreeItem::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (editor != object)
|
||||
if (editor != object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LineEditCanceled(event)) {
|
||||
QMetaObject::invokeMethod(this, "ExitEditMode", Qt::QueuedConnection, Q_ARG(bool, false));
|
||||
@@ -554,11 +565,12 @@ void SourceTreeItem::ExpandClicked(bool checked)
|
||||
|
||||
obs_data_set_bool(data, "collapsed", checked);
|
||||
|
||||
if (!checked)
|
||||
if (!checked) {
|
||||
tree->GetStm()->ExpandGroup(sceneitem);
|
||||
else
|
||||
} else {
|
||||
tree->GetStm()->CollapseGroup(sceneitem);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTreeItem::Select()
|
||||
{
|
||||
|
||||
@@ -163,8 +163,9 @@ void SourceTreeModel::ReorderItems()
|
||||
beginMoveRows(QModelIndex(), idx1Old, idx1Old + count - 1, QModelIndex(), idx1New + count);
|
||||
for (i = 0; i < count; i++) {
|
||||
int to = idx1New + count;
|
||||
if (to > idx1Old)
|
||||
if (to > idx1Old) {
|
||||
to--;
|
||||
}
|
||||
MoveItem(items, idx1Old, to);
|
||||
}
|
||||
endMoveRows();
|
||||
@@ -194,8 +195,9 @@ void SourceTreeModel::Remove(obs_sceneitem_t *item)
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == -1)
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int startIdx = idx;
|
||||
int endIdx = idx;
|
||||
@@ -208,27 +210,30 @@ void SourceTreeModel::Remove(obs_sceneitem_t *item)
|
||||
obs_sceneitem_t *subitem = items[i];
|
||||
obs_scene_t *subscene = obs_sceneitem_get_scene(subitem);
|
||||
|
||||
if (subscene == scene)
|
||||
if (subscene == scene) {
|
||||
endIdx = i;
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), startIdx, endIdx);
|
||||
items.remove(idx, endIdx - startIdx + 1);
|
||||
endRemoveRows();
|
||||
|
||||
if (is_group)
|
||||
if (is_group) {
|
||||
UpdateGroupState(true);
|
||||
}
|
||||
|
||||
OBSBasic::Get()->UpdateContextBarDeferred();
|
||||
}
|
||||
|
||||
OBSSceneItem SourceTreeModel::Get(int idx)
|
||||
{
|
||||
if (idx == -1 || idx >= items.count())
|
||||
if (idx == -1 || idx >= items.count()) {
|
||||
return OBSSceneItem();
|
||||
}
|
||||
return items[idx];
|
||||
}
|
||||
|
||||
@@ -255,8 +260,9 @@ QVariant SourceTreeModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
Qt::ItemFlags SourceTreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
if (!index.isValid()) {
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
obs_sceneitem_t *item = items[index.row()];
|
||||
bool is_group = obs_sceneitem_is_group(item);
|
||||
@@ -278,8 +284,9 @@ QString SourceTreeModel::GetNewGroupName()
|
||||
int i = 2;
|
||||
for (;;) {
|
||||
OBSSourceAutoRelease group = obs_get_source_by_name(QT_TO_UTF8(name));
|
||||
if (!group)
|
||||
if (!group) {
|
||||
break;
|
||||
}
|
||||
name = QTStr("Basic.Main.Group").arg(QString::number(i++));
|
||||
}
|
||||
|
||||
@@ -290,8 +297,9 @@ void SourceTreeModel::AddGroup()
|
||||
{
|
||||
QString name = GetNewGroupName();
|
||||
obs_sceneitem_t *group = obs_scene_add_group(GetCurrentScene(), QT_TO_UTF8(name));
|
||||
if (!group)
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
items.insert(0, group);
|
||||
@@ -305,8 +313,9 @@ void SourceTreeModel::AddGroup()
|
||||
|
||||
void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
||||
{
|
||||
if (indices.count() == 0)
|
||||
if (indices.count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
OBSScene scene = GetCurrentScene();
|
||||
@@ -329,8 +338,9 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
||||
|
||||
main->undo_s.push_disabled();
|
||||
|
||||
for (obs_sceneitem_t *item : item_order)
|
||||
for (obs_sceneitem_t *item : item_order) {
|
||||
obs_sceneitem_select(item, false);
|
||||
}
|
||||
|
||||
hasGroups = true;
|
||||
st->UpdateWidgets(true);
|
||||
@@ -349,8 +359,9 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
||||
void SourceTreeModel::UngroupSelectedGroups(QModelIndexList &indices)
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
if (indices.count() == 0)
|
||||
if (indices.count() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSScene scene = main->GetCurrentScene();
|
||||
OBSData undoData = main->BackupScene(scene);
|
||||
@@ -369,8 +380,9 @@ void SourceTreeModel::UngroupSelectedGroups(QModelIndexList &indices)
|
||||
void SourceTreeModel::ExpandGroup(obs_sceneitem_t *item)
|
||||
{
|
||||
int itemIdx = items.indexOf(item);
|
||||
if (itemIdx == -1)
|
||||
if (itemIdx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
itemIdx++;
|
||||
|
||||
@@ -379,12 +391,14 @@ void SourceTreeModel::ExpandGroup(obs_sceneitem_t *item)
|
||||
QVector<OBSSceneItem> subItems;
|
||||
obs_scene_enum_items(scene, enumItem, &subItems);
|
||||
|
||||
if (!subItems.size())
|
||||
if (!subItems.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), itemIdx, itemIdx + subItems.size() - 1);
|
||||
for (int i = 0; i < subItems.size(); i++)
|
||||
for (int i = 0; i < subItems.size(); i++) {
|
||||
items.insert(i + itemIdx, subItems[i]);
|
||||
}
|
||||
endInsertRows();
|
||||
|
||||
st->UpdateWidgets();
|
||||
@@ -401,14 +415,16 @@ void SourceTreeModel::CollapseGroup(obs_sceneitem_t *item)
|
||||
obs_scene_t *itemScene = obs_sceneitem_get_scene(items[i]);
|
||||
|
||||
if (itemScene == scene) {
|
||||
if (startIdx == -1)
|
||||
if (startIdx == -1) {
|
||||
startIdx = i;
|
||||
}
|
||||
endIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (startIdx == -1)
|
||||
if (startIdx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), startIdx, endIdx);
|
||||
items.remove(startIdx, endIdx - startIdx + 1);
|
||||
|
||||
@@ -40,9 +40,10 @@ TextSourceToolbar::TextSourceToolbar(QWidget *parent, OBSSource source)
|
||||
bool single_line = !read_from_file && (!text || (strchr(text, '\n') == nullptr));
|
||||
ui->emptySpace->setVisible(!single_line);
|
||||
ui->text->setVisible(single_line);
|
||||
if (single_line)
|
||||
if (single_line) {
|
||||
ui->text->setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
TextSourceToolbar::~TextSourceToolbar() {}
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@ static int CountVideoSources()
|
||||
{
|
||||
int count = 0;
|
||||
auto countSources = [](void *param, obs_source_t *source) {
|
||||
if (!source)
|
||||
if (!source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
if ((flags & OBS_SOURCE_VIDEO) != 0)
|
||||
if ((flags & OBS_SOURCE_VIDEO) != 0) {
|
||||
(*static_cast<int *>(param))++;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
@@ -28,12 +30,14 @@ static int CountVideoSources()
|
||||
bool UIValidation::NoSourcesConfirmation(QWidget *parent)
|
||||
{
|
||||
// There are sources, don't need confirmation
|
||||
if (CountVideoSources() != 0)
|
||||
if (CountVideoSources() != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ignore no video if no parent is visible to alert on
|
||||
if (!parent->isVisible())
|
||||
if (!parent->isVisible()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
QString msg = QTStr("NoSources.Text");
|
||||
msg += "\n\n";
|
||||
@@ -48,16 +52,18 @@ bool UIValidation::NoSourcesConfirmation(QWidget *parent)
|
||||
messageBox.setIcon(QMessageBox::Question);
|
||||
messageBox.exec();
|
||||
|
||||
if (messageBox.clickedButton() != yesButton)
|
||||
if (messageBox.clickedButton() != yesButton) {
|
||||
return false;
|
||||
else
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
StreamSettingsAction UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
||||
{
|
||||
if (obs_service_can_try_to_connect(service))
|
||||
if (obs_service_can_try_to_connect(service)) {
|
||||
return StreamSettingsAction::ContinueStream;
|
||||
}
|
||||
|
||||
char const *serviceType = obs_service_get_type(service);
|
||||
bool isCustomService = (strcmp(serviceType, "rtmp_custom") == 0);
|
||||
@@ -100,10 +106,12 @@ StreamSettingsAction UIValidation::StreamSettingsConfirmation(QWidget *parent, O
|
||||
messageBox.setIcon(QMessageBox::Warning);
|
||||
messageBox.exec();
|
||||
|
||||
if (messageBox.clickedButton() == settings)
|
||||
if (messageBox.clickedButton() == settings) {
|
||||
return StreamSettingsAction::OpenSettings;
|
||||
if (messageBox.clickedButton() == cancel)
|
||||
}
|
||||
if (messageBox.clickedButton() == cancel) {
|
||||
return StreamSettingsAction::Cancel;
|
||||
}
|
||||
|
||||
return StreamSettingsAction::ContinueStream;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ void UrlPushButton::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
QUrl openUrl = m_targetUrl;
|
||||
if (openUrl.isEmpty())
|
||||
if (openUrl.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDesktopServices::openUrl(openUrl);
|
||||
}
|
||||
|
||||
@@ -14,13 +14,15 @@ void VisibilityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem
|
||||
|
||||
QObject *parentObj = parent();
|
||||
QListWidget *list = qobject_cast<QListWidget *>(parentObj);
|
||||
if (!list)
|
||||
if (!list) {
|
||||
return;
|
||||
}
|
||||
|
||||
QListWidgetItem *item = list->item(index.row());
|
||||
VisibilityItemWidget *widget = qobject_cast<VisibilityItemWidget *>(list->itemWidget(item));
|
||||
if (!widget)
|
||||
if (!widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool selected = option.state.testFlag(QStyle::State_Selected);
|
||||
bool active = option.state.testFlag(QStyle::State_Active);
|
||||
@@ -40,10 +42,11 @@ void VisibilityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem
|
||||
|
||||
QPalette::ColorRole role;
|
||||
|
||||
if (selected && active)
|
||||
if (selected && active) {
|
||||
role = highlightRole;
|
||||
else
|
||||
} else {
|
||||
role = QPalette::WindowText;
|
||||
}
|
||||
|
||||
widget->SetColor(palette.color(group, role), active, selected);
|
||||
}
|
||||
@@ -51,8 +54,9 @@ void VisibilityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem
|
||||
bool VisibilityItemDelegate::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
QWidget *editor = qobject_cast<QWidget *>(object);
|
||||
if (!editor)
|
||||
if (!editor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
|
||||
@@ -41,15 +41,17 @@ void VisibilityItemWidget::OBSSourceEnabled(void *param, calldata_t *data)
|
||||
|
||||
void VisibilityItemWidget::SourceEnabled(bool enabled)
|
||||
{
|
||||
if (vis->isChecked() != enabled)
|
||||
if (vis->isChecked() != enabled) {
|
||||
vis->setChecked(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SetColor(const QColor &color, bool active_, bool selected_)
|
||||
{
|
||||
/* Do not update unless the state has actually changed */
|
||||
if (active_ == active && selected_ == selected)
|
||||
if (active_ == active && selected_ == selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPalette pal = vis->palette();
|
||||
pal.setColor(QPalette::WindowText, color);
|
||||
|
||||
@@ -27,10 +27,11 @@ QVariant VolumeAccessibleInterface::currentValue() const
|
||||
QString text;
|
||||
float db = obs_fader_get_db(slider()->fad);
|
||||
|
||||
if (db < -96.0f)
|
||||
if (db < -96.0f) {
|
||||
text = "-inf dB";
|
||||
else
|
||||
} else {
|
||||
text = QString::number(db, 'f', 1).append(" dB");
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,9 @@ void WindowCaptureToolbar::Init()
|
||||
ui->activateButton = nullptr;
|
||||
|
||||
obs_module_t *mod = get_os_module("win-capture", "mac-capture", "linux-capture");
|
||||
if (!mod)
|
||||
if (!mod) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *device_str = get_os_text(mod, "WindowCapture.Window", "WindowUtils.Window", "Window");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
@@ -68,17 +68,20 @@ static bool IsWhitespace(char ch)
|
||||
|
||||
static void CleanWhitespace(std::string &str)
|
||||
{
|
||||
while (str.size() && IsWhitespace(str.back()))
|
||||
while (str.size() && IsWhitespace(str.back())) {
|
||||
str.erase(str.end() - 1);
|
||||
while (str.size() && IsWhitespace(str.front()))
|
||||
}
|
||||
while (str.size() && IsWhitespace(str.front())) {
|
||||
str.erase(str.begin());
|
||||
}
|
||||
}
|
||||
|
||||
bool NameDialog::AskForName(QWidget *parent, const QString &title, const QString &text, std::string &userTextInput,
|
||||
const QString &placeHolder, int maxSize)
|
||||
{
|
||||
if (maxSize <= 0 || maxSize > 32767)
|
||||
if (maxSize <= 0 || maxSize > 32767) {
|
||||
maxSize = 170;
|
||||
}
|
||||
|
||||
NameDialog dialog(parent);
|
||||
dialog.setWindowTitle(title);
|
||||
|
||||
@@ -92,19 +92,22 @@ void OAuthLogin::urlChanged(const QString &url)
|
||||
{
|
||||
std::string uri = get_token ? "access_token=" : "code=";
|
||||
int code_idx = url.indexOf(uri.c_str());
|
||||
if (code_idx == -1)
|
||||
if (code_idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!url.startsWith(OAUTH_BASE_URL))
|
||||
if (!url.startsWith(OAUTH_BASE_URL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
code_idx += (int)uri.size();
|
||||
|
||||
int next_idx = url.indexOf("&", code_idx);
|
||||
if (next_idx != -1)
|
||||
if (next_idx != -1) {
|
||||
code = url.mid(code_idx, next_idx - code_idx);
|
||||
else
|
||||
} else {
|
||||
code = url.right(url.size() - code_idx);
|
||||
}
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
@@ -21,10 +21,11 @@ OBSAbout::OBSAbout(QWidget *parent) : QDialog(parent), ui(new Ui::OBSAbout)
|
||||
|
||||
QString bitness;
|
||||
|
||||
if (sizeof(void *) == 4)
|
||||
if (sizeof(void *) == 4) {
|
||||
bitness = " (32 bit)";
|
||||
else if (sizeof(void *) == 8)
|
||||
} else if (sizeof(void *) == 8) {
|
||||
bitness = " (64 bit)";
|
||||
}
|
||||
|
||||
QString ver = obs_get_version_string();
|
||||
|
||||
@@ -80,8 +81,9 @@ void OBSAbout::ShowAbout()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
|
||||
if (main->patronJson.empty())
|
||||
if (main->patronJson.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string error;
|
||||
Json json = Json::parse(main->patronJson, error);
|
||||
@@ -111,12 +113,14 @@ void OBSAbout::ShowAbout()
|
||||
text += "\">";
|
||||
}
|
||||
text += QT_UTF8(name.c_str()).toHtmlEscaped();
|
||||
if (!link.empty())
|
||||
if (!link.empty()) {
|
||||
text += "</a>";
|
||||
}
|
||||
|
||||
if (first)
|
||||
if (first) {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
ui->textBrowser->setHtml(text);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ OBSBasicAdvAudio::OBSBasicAdvAudio(QWidget *parent) : QDialog(parent), ui(new Ui
|
||||
|
||||
VolumeType volType = (VolumeType)config_get_int(App()->GetUserConfig(), "BasicWindow", "AdvAudioVolumeType");
|
||||
|
||||
if (volType == VolumeType::Percent)
|
||||
if (volType == VolumeType::Percent) {
|
||||
ui->usePercent->setChecked(true);
|
||||
}
|
||||
|
||||
installEventFilter(CreateShortcutFilter());
|
||||
|
||||
@@ -35,8 +36,9 @@ OBSBasicAdvAudio::~OBSBasicAdvAudio()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
|
||||
for (size_t i = 0; i < controls.size(); ++i)
|
||||
for (size_t i = 0; i < controls.size(); ++i) {
|
||||
delete controls[i];
|
||||
}
|
||||
|
||||
main->SaveProject();
|
||||
}
|
||||
@@ -47,8 +49,9 @@ bool OBSBasicAdvAudio::EnumSources(void *param, obs_source_t *source)
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
|
||||
if ((flags & OBS_SOURCE_AUDIO) != 0 &&
|
||||
(dialog->showInactive || (obs_source_active(source) && obs_source_audio_active(source))))
|
||||
(dialog->showInactive || (obs_source_active(source) && obs_source_audio_active(source)))) {
|
||||
dialog->AddAudioSource(source);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -71,17 +74,19 @@ void OBSBasicAdvAudio::OBSSourceActivated(void *param, calldata_t *calldata)
|
||||
{
|
||||
OBSSource source((obs_source_t *)calldata_ptr(calldata, "source"));
|
||||
|
||||
if (obs_source_audio_active(source))
|
||||
if (obs_source_audio_active(source)) {
|
||||
QMetaObject::invokeMethod(static_cast<OBSBasicAdvAudio *>(param), "SourceAdded",
|
||||
Q_ARG(OBSSource, source));
|
||||
}
|
||||
}
|
||||
|
||||
inline void OBSBasicAdvAudio::AddAudioSource(obs_source_t *source)
|
||||
{
|
||||
for (size_t i = 0; i < controls.size(); i++) {
|
||||
if (controls[i]->GetSource() == source)
|
||||
if (controls[i]->GetSource() == source) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
OBSAdvAudioCtrl *control = new OBSAdvAudioCtrl(ui->mainLayout, source);
|
||||
|
||||
InsertQObjectByName(controls, control);
|
||||
@@ -95,8 +100,9 @@ void OBSBasicAdvAudio::SourceAdded(OBSSource source)
|
||||
{
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
|
||||
if ((flags & OBS_SOURCE_AUDIO) == 0)
|
||||
if ((flags & OBS_SOURCE_AUDIO) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddAudioSource(source);
|
||||
}
|
||||
@@ -105,8 +111,9 @@ void OBSBasicAdvAudio::SourceRemoved(OBSSource source)
|
||||
{
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
|
||||
if ((flags & OBS_SOURCE_AUDIO) == 0)
|
||||
if ((flags & OBS_SOURCE_AUDIO) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < controls.size(); i++) {
|
||||
if (controls[i]->GetSource() == source) {
|
||||
@@ -121,13 +128,15 @@ void OBSBasicAdvAudio::on_usePercent_toggled(bool checked)
|
||||
{
|
||||
VolumeType type;
|
||||
|
||||
if (checked)
|
||||
if (checked) {
|
||||
type = VolumeType::Percent;
|
||||
else
|
||||
} else {
|
||||
type = VolumeType::dB;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < controls.size(); i++)
|
||||
for (size_t i = 0; i < controls.size(); i++) {
|
||||
controls[i]->SetVolumeWidget(type);
|
||||
}
|
||||
|
||||
config_set_int(App()->GetUserConfig(), "BasicWindow", "AdvAudioVolumeType", (int)type);
|
||||
}
|
||||
@@ -139,8 +148,9 @@ void OBSBasicAdvAudio::on_activeOnly_toggled(bool checked)
|
||||
|
||||
void OBSBasicAdvAudio::SetShowInactive(bool show)
|
||||
{
|
||||
if (showInactive == show)
|
||||
if (showInactive == show) {
|
||||
return;
|
||||
}
|
||||
|
||||
showInactive = show;
|
||||
|
||||
|
||||
@@ -111,8 +111,9 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
||||
ui->effectFilters->setFocus();
|
||||
}
|
||||
|
||||
if (audioOnly || (audio && !async))
|
||||
if (audioOnly || (audio && !async)) {
|
||||
ui->asyncLabel->setText(QTStr("Basic.Filters.AudioFilters"));
|
||||
}
|
||||
|
||||
if (async && audio && ui->asyncFilters->count() == 0) {
|
||||
UpdateSplitter(false);
|
||||
@@ -132,8 +133,9 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
||||
if ((caps & OBS_SOURCE_VIDEO) != 0) {
|
||||
ui->rightLayout->setContentsMargins(0, 0, 0, 0);
|
||||
ui->preview->show();
|
||||
if (drawable_type)
|
||||
if (drawable_type) {
|
||||
connect(ui->preview, &OBSQTDisplay::DisplayCreated, this, addDrawCallback);
|
||||
}
|
||||
} else {
|
||||
ui->rightLayout->setContentsMargins(0, noPreviewMargin, 0, 0);
|
||||
ui->preview->hide();
|
||||
@@ -162,13 +164,15 @@ void OBSBasicFilters::Init()
|
||||
|
||||
inline OBSSource OBSBasicFilters::GetFilter(int row, bool async)
|
||||
{
|
||||
if (row == -1)
|
||||
if (row == -1) {
|
||||
return OBSSource();
|
||||
}
|
||||
|
||||
QListWidget *list = async ? ui->asyncFilters : ui->effectFilters;
|
||||
QListWidgetItem *item = list->item(row);
|
||||
if (!item)
|
||||
if (!item) {
|
||||
return OBSSource();
|
||||
}
|
||||
|
||||
QVariant v = item->data(Qt::UserRole);
|
||||
return v.value<OBSSource>();
|
||||
@@ -244,8 +248,9 @@ void OBSBasicFilters::UpdatePropertiesView(int row, bool async)
|
||||
}
|
||||
}
|
||||
|
||||
if (!filter)
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease settings = obs_source_get_settings(filter);
|
||||
|
||||
@@ -287,8 +292,9 @@ void OBSBasicFilters::AddFilter(OBSSource filter, bool focus)
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(filter));
|
||||
|
||||
list->addItem(item);
|
||||
if (focus)
|
||||
if (focus) {
|
||||
list->setCurrentItem(item);
|
||||
}
|
||||
|
||||
SetupVisibilityItem(list, item, filter);
|
||||
}
|
||||
@@ -312,8 +318,9 @@ void OBSBasicFilters::RemoveFilter(OBSSource filter)
|
||||
|
||||
const char *filterName = obs_source_get_name(filter);
|
||||
const char *sourceName = obs_source_get_name(source);
|
||||
if (!sourceName || !filterName)
|
||||
if (!sourceName || !filterName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *filterId = obs_source_get_id(filter);
|
||||
|
||||
@@ -348,10 +355,11 @@ void OBSBasicFilters::ReorderFilter(QListWidget *list, obs_source_t *filter, siz
|
||||
list->insertItem((int)idx, listItem);
|
||||
SetupVisibilityItem(list, listItem, filterItem);
|
||||
|
||||
if (sel)
|
||||
if (sel) {
|
||||
list->setCurrentRow((int)idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -383,8 +391,9 @@ void OBSBasicFilters::ReorderFilters()
|
||||
|
||||
void OBSBasicFilters::UpdateFilters()
|
||||
{
|
||||
if (!source)
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClearListItems(ui->effectFilters);
|
||||
ClearListItems(ui->asyncFilters);
|
||||
@@ -417,8 +426,9 @@ void OBSBasicFilters::UpdateSplitter(bool show_splitter_frame)
|
||||
{
|
||||
bool show_splitter_handle = show_splitter_frame;
|
||||
uint32_t caps = obs_source_get_output_flags(source);
|
||||
if ((caps & OBS_SOURCE_VIDEO) == 0)
|
||||
if ((caps & OBS_SOURCE_VIDEO) == 0) {
|
||||
show_splitter_handle = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ui->rightLayout->count(); i++) {
|
||||
QSplitterHandle *hndl = ui->rightLayout->handle(i);
|
||||
@@ -438,8 +448,9 @@ static bool filter_compatible(bool async, uint32_t sourceFlags, uint32_t filterF
|
||||
bool asyncSource = (sourceFlags & OBS_SOURCE_ASYNC) != 0;
|
||||
|
||||
if (async && ((audioOnly && filterVideo) || (!audio && !asyncSource) || (filterAudio && !audio) ||
|
||||
(!asyncSource && !filterAudio)))
|
||||
(!asyncSource && !filterAudio))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (async && (filterAudio || filterAsync)) || (!async && !filterAudio && !filterAsync);
|
||||
}
|
||||
@@ -465,12 +476,15 @@ QMenu *OBSBasicFilters::CreateAddFilterPopupMenu(bool async)
|
||||
const char *name = obs_source_get_display_name(type_str);
|
||||
uint32_t caps = obs_get_source_output_flags(type_str);
|
||||
|
||||
if ((caps & OBS_SOURCE_DEPRECATED) != 0)
|
||||
if ((caps & OBS_SOURCE_DEPRECATED) != 0) {
|
||||
continue;
|
||||
if ((caps & OBS_SOURCE_CAP_DISABLED) != 0)
|
||||
}
|
||||
if ((caps & OBS_SOURCE_CAP_DISABLED) != 0) {
|
||||
continue;
|
||||
if ((caps & OBS_SOURCE_CAP_OBSOLETE) != 0)
|
||||
}
|
||||
if ((caps & OBS_SOURCE_CAP_OBSOLETE) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
types.emplace_back(type_str, name);
|
||||
}
|
||||
@@ -481,8 +495,9 @@ QMenu *OBSBasicFilters::CreateAddFilterPopupMenu(bool async)
|
||||
for (FilterInfo &type : types) {
|
||||
uint32_t filterFlags = obs_get_source_output_flags(type.type.c_str());
|
||||
|
||||
if (!filter_compatible(async, sourceFlags, filterFlags))
|
||||
if (!filter_compatible(async, sourceFlags, filterFlags)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QAction *popupItem = new QAction(QT_UTF8(type.name.c_str()), this);
|
||||
popupItem->setData(QT_UTF8(type.type.c_str()));
|
||||
@@ -515,8 +530,9 @@ void OBSBasicFilters::AddNewFilter(const char *id)
|
||||
|
||||
bool success = NameDialog::AskForName(this, QTStr("Basic.Filters.AddFilter.Title"),
|
||||
QTStr("Basic.Filters.AddFilter.Text"), name, text);
|
||||
if (!success)
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (name.empty()) {
|
||||
OBSMessageBox::warning(this, QTStr("NoNameEntered.Title"), QTStr("NoNameEntered.Text"));
|
||||
@@ -586,8 +602,9 @@ void OBSBasicFilters::AddNewFilter(const char *id)
|
||||
void OBSBasicFilters::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QDialog::closeEvent(event);
|
||||
if (!event->isAccepted())
|
||||
if (!event->isAccepted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_display_remove_draw_callback(ui->preview->GetDisplay(), OBSBasicFilters::DrawPreview, this);
|
||||
|
||||
@@ -656,8 +673,9 @@ void OBSBasicFilters::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
||||
{
|
||||
OBSBasicFilters *window = static_cast<OBSBasicFilters *>(data);
|
||||
|
||||
if (!window->source)
|
||||
if (!window->source) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sourceCX = max(obs_source_get_width(window->source), 1u);
|
||||
uint32_t sourceCY = max(obs_source_get_height(window->source), 1u);
|
||||
@@ -707,32 +725,36 @@ void OBSBasicFilters::on_addAsyncFilter_clicked()
|
||||
{
|
||||
ui->asyncFilters->setFocus();
|
||||
QScopedPointer<QMenu> popup(CreateAddFilterPopupMenu(true));
|
||||
if (popup)
|
||||
if (popup) {
|
||||
popup->exec(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_removeAsyncFilter_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
if (filter) {
|
||||
if (QueryRemove(this, filter))
|
||||
if (QueryRemove(this, filter)) {
|
||||
delete_filter(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveAsyncFilterUp_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
if (filter)
|
||||
if (filter) {
|
||||
obs_source_filter_set_order(source, filter, OBS_ORDER_MOVE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveAsyncFilterDown_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
if (filter)
|
||||
if (filter) {
|
||||
obs_source_filter_set_order(source, filter, OBS_ORDER_MOVE_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_asyncFilters_GotFocus()
|
||||
{
|
||||
@@ -749,9 +771,10 @@ void OBSBasicFilters::on_addEffectFilter_clicked()
|
||||
{
|
||||
ui->effectFilters->setFocus();
|
||||
QScopedPointer<QMenu> popup(CreateAddFilterPopupMenu(false));
|
||||
if (popup)
|
||||
if (popup) {
|
||||
popup->exec(QCursor::pos());
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_removeEffectFilter_clicked()
|
||||
{
|
||||
@@ -766,16 +789,18 @@ void OBSBasicFilters::on_removeEffectFilter_clicked()
|
||||
void OBSBasicFilters::on_moveEffectFilterUp_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||
if (filter)
|
||||
if (filter) {
|
||||
obs_source_filter_set_order(source, filter, OBS_ORDER_MOVE_UP);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveEffectFilterDown_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||
if (filter)
|
||||
if (filter) {
|
||||
obs_source_filter_set_order(source, filter, OBS_ORDER_MOVE_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_effectFilters_GotFocus()
|
||||
{
|
||||
@@ -790,35 +815,39 @@ void OBSBasicFilters::on_effectFilters_currentRowChanged(int row)
|
||||
|
||||
void OBSBasicFilters::on_actionRemoveFilter_triggered()
|
||||
{
|
||||
if (ui->asyncFilters->hasFocus())
|
||||
if (ui->asyncFilters->hasFocus()) {
|
||||
on_removeAsyncFilter_clicked();
|
||||
else if (ui->effectFilters->hasFocus())
|
||||
} else if (ui->effectFilters->hasFocus()) {
|
||||
on_removeEffectFilter_clicked();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_actionMoveUp_triggered()
|
||||
{
|
||||
if (ui->asyncFilters->hasFocus())
|
||||
if (ui->asyncFilters->hasFocus()) {
|
||||
on_moveAsyncFilterUp_clicked();
|
||||
else if (ui->effectFilters->hasFocus())
|
||||
} else if (ui->effectFilters->hasFocus()) {
|
||||
on_moveEffectFilterUp_clicked();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_actionMoveDown_triggered()
|
||||
{
|
||||
if (ui->asyncFilters->hasFocus())
|
||||
if (ui->asyncFilters->hasFocus()) {
|
||||
on_moveAsyncFilterDown_clicked();
|
||||
else if (ui->effectFilters->hasFocus())
|
||||
} else if (ui->effectFilters->hasFocus()) {
|
||||
on_moveEffectFilterDown_clicked();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_actionRenameFilter_triggered()
|
||||
{
|
||||
if (ui->asyncFilters->hasFocus())
|
||||
if (ui->asyncFilters->hasFocus()) {
|
||||
RenameAsyncFilter();
|
||||
else if (ui->effectFilters->hasFocus())
|
||||
} else if (ui->effectFilters->hasFocus()) {
|
||||
RenameEffectFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async)
|
||||
{
|
||||
@@ -828,8 +857,9 @@ void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async)
|
||||
QMenu popup(window());
|
||||
|
||||
QPointer<QMenu> addMenu = CreateAddFilterPopupMenu(async);
|
||||
if (addMenu)
|
||||
if (addMenu) {
|
||||
popup.addMenu(addMenu);
|
||||
}
|
||||
|
||||
if (item) {
|
||||
popup.addSeparator();
|
||||
@@ -862,8 +892,9 @@ void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async)
|
||||
|
||||
void OBSBasicFilters::EditItem(QListWidgetItem *item, bool async)
|
||||
{
|
||||
if (editActive)
|
||||
if (editActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags = item->flags();
|
||||
OBSSource filter = item->data(Qt::UserRole).value<OBSSource>();
|
||||
@@ -893,8 +924,9 @@ void OBSBasicFilters::DuplicateItem(QListWidgetItem *item)
|
||||
|
||||
bool success = NameDialog::AskForName(this, QTStr("Basic.Filters.AddFilter.Title"),
|
||||
QTStr("Basic.Filters.AddFilter.Text"), name, text);
|
||||
if (!success)
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (name.empty()) {
|
||||
OBSMessageBox::warning(this, QTStr("NoNameEntered.Title"), QTStr("NoNameEntered.Text"));
|
||||
@@ -953,8 +985,9 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list)
|
||||
bool sameName = (name == prevName);
|
||||
OBSSourceAutoRelease foundFilter = nullptr;
|
||||
|
||||
if (!sameName)
|
||||
if (!sameName) {
|
||||
foundFilter = obs_source_get_filter_by_name(source, name.c_str());
|
||||
}
|
||||
|
||||
if (foundFilter || name.empty() || sameName) {
|
||||
listItem->setText(QT_UTF8(prevName));
|
||||
@@ -1015,11 +1048,13 @@ void OBSBasicFilters::ResetFilters()
|
||||
|
||||
OBSSource filter = GetFilter(row, isAsync);
|
||||
|
||||
if (!filter)
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ConfirmReset(this))
|
||||
if (!ConfirmReset(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease settings = obs_source_get_settings(filter);
|
||||
|
||||
@@ -1028,8 +1063,9 @@ void OBSBasicFilters::ResetFilters()
|
||||
|
||||
obs_data_clear(settings);
|
||||
|
||||
if (!view->DeferUpdate())
|
||||
if (!view->DeferUpdate()) {
|
||||
obs_source_update(filter, nullptr);
|
||||
}
|
||||
|
||||
view->ReloadProperties();
|
||||
}
|
||||
@@ -1038,10 +1074,11 @@ void OBSBasicFilters::CopyFilter()
|
||||
{
|
||||
OBSSource filter = nullptr;
|
||||
|
||||
if (isAsync)
|
||||
if (isAsync) {
|
||||
filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
else
|
||||
} else {
|
||||
filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||
}
|
||||
|
||||
main->copyFilter = OBSGetWeakRef(filter);
|
||||
}
|
||||
@@ -1049,8 +1086,9 @@ void OBSBasicFilters::CopyFilter()
|
||||
void OBSBasicFilters::PasteFilter()
|
||||
{
|
||||
OBSSource filter = OBSGetStrongRef(main->copyFilter);
|
||||
if (!filter)
|
||||
if (!filter) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataArrayAutoRelease undo_array = obs_source_backup_filters(source);
|
||||
obs_source_copy_single_filter(source, filter);
|
||||
@@ -1105,17 +1143,19 @@ void OBSBasicFilters::FiltersMoved(const QModelIndex &, int srcIdxStart, int, co
|
||||
QListWidget *list = isAsync ? ui->asyncFilters : ui->effectFilters;
|
||||
int neighborIdx = 0;
|
||||
|
||||
if (srcIdxStart < list->currentRow())
|
||||
if (srcIdxStart < list->currentRow()) {
|
||||
neighborIdx = list->currentRow() - 1;
|
||||
else if (srcIdxStart > list->currentRow())
|
||||
} else if (srcIdxStart > list->currentRow()) {
|
||||
neighborIdx = list->currentRow() + 1;
|
||||
else
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (neighborIdx > list->count() - 1)
|
||||
if (neighborIdx > list->count() - 1) {
|
||||
neighborIdx = list->count() - 1;
|
||||
else if (neighborIdx < 0)
|
||||
} else if (neighborIdx < 0) {
|
||||
neighborIdx = 0;
|
||||
}
|
||||
|
||||
OBSSource neighbor = GetFilter(neighborIdx, isAsync);
|
||||
int idx = obs_source_filter_get_index(source, neighbor);
|
||||
|
||||
@@ -115,9 +115,10 @@ public:
|
||||
|
||||
inline void UpdateSource(obs_source_t *target)
|
||||
{
|
||||
if (source == target)
|
||||
if (source == target) {
|
||||
UpdateFilters();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
@@ -59,8 +59,9 @@ OBSBasicInteraction::OBSBasicInteraction(QWidget *parent, OBSSource source_)
|
||||
ui->preview->setFocusPolicy(Qt::StrongFocus);
|
||||
ui->preview->installEventFilter(eventFilter.get());
|
||||
|
||||
if (cx > 400 && cy > 400)
|
||||
if (cx > 400 && cy > 400) {
|
||||
resize(cx, cy);
|
||||
}
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
setWindowTitle(QTStr("Basic.InteractionWindow").arg(QT_UTF8(name)));
|
||||
@@ -123,8 +124,9 @@ void OBSBasicInteraction::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
||||
{
|
||||
OBSBasicInteraction *window = static_cast<OBSBasicInteraction *>(data);
|
||||
|
||||
if (!window->source)
|
||||
if (!window->source) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sourceCX = max(obs_source_get_width(window->source), 1u);
|
||||
uint32_t sourceCY = max(obs_source_get_height(window->source), 1u);
|
||||
@@ -154,8 +156,9 @@ void OBSBasicInteraction::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
||||
void OBSBasicInteraction::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QDialog::closeEvent(event);
|
||||
if (!event->isAccepted())
|
||||
if (!event->isAccepted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
config_set_int(App()->GetAppConfig(), "InteractionWindow", "cx", width());
|
||||
config_set_int(App()->GetAppConfig(), "InteractionWindow", "cy", height());
|
||||
@@ -189,26 +192,32 @@ static int TranslateQtKeyboardEventModifiers(QInputEvent *event, bool mouseEvent
|
||||
{
|
||||
int obsModifiers = INTERACT_NONE;
|
||||
|
||||
if (event->modifiers().testFlag(Qt::ShiftModifier))
|
||||
if (event->modifiers().testFlag(Qt::ShiftModifier)) {
|
||||
obsModifiers |= INTERACT_SHIFT_KEY;
|
||||
if (event->modifiers().testFlag(Qt::AltModifier))
|
||||
}
|
||||
if (event->modifiers().testFlag(Qt::AltModifier)) {
|
||||
obsModifiers |= INTERACT_ALT_KEY;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
// Mac: Meta = Control, Control = Command
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier))
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier)) {
|
||||
obsModifiers |= INTERACT_COMMAND_KEY;
|
||||
if (event->modifiers().testFlag(Qt::MetaModifier))
|
||||
}
|
||||
if (event->modifiers().testFlag(Qt::MetaModifier)) {
|
||||
obsModifiers |= INTERACT_CONTROL_KEY;
|
||||
}
|
||||
#else
|
||||
// Handle windows key? Can a browser even trap that key?
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier))
|
||||
if (event->modifiers().testFlag(Qt::ControlModifier)) {
|
||||
obsModifiers |= INTERACT_CONTROL_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mouseEvent) {
|
||||
if (event->modifiers().testFlag(Qt::KeypadModifier))
|
||||
if (event->modifiers().testFlag(Qt::KeypadModifier)) {
|
||||
obsModifiers |= INTERACT_IS_KEY_PAD;
|
||||
}
|
||||
}
|
||||
|
||||
return obsModifiers;
|
||||
}
|
||||
@@ -217,12 +226,15 @@ static int TranslateQtMouseEventModifiers(QMouseEvent *event)
|
||||
{
|
||||
int modifiers = TranslateQtKeyboardEventModifiers(event, true);
|
||||
|
||||
if (event->buttons().testFlag(Qt::LeftButton))
|
||||
if (event->buttons().testFlag(Qt::LeftButton)) {
|
||||
modifiers |= INTERACT_MOUSE_LEFT;
|
||||
if (event->buttons().testFlag(Qt::MiddleButton))
|
||||
}
|
||||
if (event->buttons().testFlag(Qt::MiddleButton)) {
|
||||
modifiers |= INTERACT_MOUSE_MIDDLE;
|
||||
if (event->buttons().testFlag(Qt::RightButton))
|
||||
}
|
||||
if (event->buttons().testFlag(Qt::RightButton)) {
|
||||
modifiers |= INTERACT_MOUSE_RIGHT;
|
||||
}
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
@@ -252,10 +264,12 @@ bool OBSBasicInteraction::GetSourceRelativeXY(int mouseX, int mouseY, int &relX,
|
||||
}
|
||||
|
||||
// Confirm mouse is inside the source
|
||||
if (relX < 0 || relX > int(sourceCX))
|
||||
if (relX < 0 || relX > int(sourceCX)) {
|
||||
return false;
|
||||
if (relY < 0 || relY > int(sourceCY))
|
||||
}
|
||||
if (relY < 0 || relY > int(sourceCY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -264,8 +278,9 @@ bool OBSBasicInteraction::HandleMouseClickEvent(QMouseEvent *event)
|
||||
{
|
||||
bool mouseUp = event->type() == QEvent::MouseButtonRelease;
|
||||
int clickCount = 1;
|
||||
if (event->type() == QEvent::MouseButtonDblClick)
|
||||
if (event->type() == QEvent::MouseButtonDblClick) {
|
||||
clickCount = 2;
|
||||
}
|
||||
|
||||
struct obs_mouse_event mouseEvent = {};
|
||||
|
||||
@@ -295,8 +310,9 @@ bool OBSBasicInteraction::HandleMouseClickEvent(QMouseEvent *event)
|
||||
QPoint pos = event->pos();
|
||||
bool insideSource = GetSourceRelativeXY(pos.x(), pos.y(), mouseEvent.x, mouseEvent.y);
|
||||
|
||||
if (mouseUp || insideSource)
|
||||
if (mouseUp || insideSource) {
|
||||
obs_source_send_mouse_click(source, &mouseEvent, button, mouseUp, clickCount);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -329,16 +345,18 @@ bool OBSBasicInteraction::HandleMouseWheelEvent(QWheelEvent *event)
|
||||
|
||||
const QPoint angleDelta = event->angleDelta();
|
||||
if (!event->pixelDelta().isNull()) {
|
||||
if (angleDelta.x())
|
||||
if (angleDelta.x()) {
|
||||
xDelta = event->pixelDelta().x();
|
||||
else
|
||||
yDelta = event->pixelDelta().y();
|
||||
} else {
|
||||
if (angleDelta.x())
|
||||
yDelta = event->pixelDelta().y();
|
||||
}
|
||||
} else {
|
||||
if (angleDelta.x()) {
|
||||
xDelta = angleDelta.x();
|
||||
else
|
||||
} else {
|
||||
yDelta = angleDelta.y();
|
||||
}
|
||||
}
|
||||
|
||||
const QPointF position = event->position();
|
||||
const int x = position.x();
|
||||
|
||||
@@ -59,8 +59,9 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
||||
ui->setupUi(this);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setFocus();
|
||||
|
||||
if (cx > 400 && cy > 400)
|
||||
if (cx > 400 && cy > 400) {
|
||||
resize(cx, cy);
|
||||
}
|
||||
|
||||
/* The OBSData constructor increments the reference once */
|
||||
obs_data_release(oldSettings);
|
||||
@@ -321,24 +322,27 @@ void OBSBasicProperties::on_buttonBox_clicked(QAbstractButton *button)
|
||||
std::string undo_data(obs_data_get_json(oldSettings));
|
||||
std::string redo_data(obs_data_get_json(new_settings));
|
||||
|
||||
if (undo_data.compare(redo_data) != 0)
|
||||
if (undo_data.compare(redo_data) != 0) {
|
||||
main->undo_s.add_action(QTStr("Undo.Properties").arg(obs_source_get_name(source)), undo_redo,
|
||||
undo_redo, undo_data, redo_data);
|
||||
}
|
||||
|
||||
acceptClicked = true;
|
||||
close();
|
||||
|
||||
if (view->DeferUpdate())
|
||||
if (view->DeferUpdate()) {
|
||||
view->UpdateSettings();
|
||||
}
|
||||
|
||||
} else if (val == QDialogButtonBox::RejectRole) {
|
||||
OBSDataAutoRelease settings = obs_source_get_settings(source);
|
||||
obs_data_clear(settings);
|
||||
|
||||
if (view->DeferUpdate())
|
||||
if (view->DeferUpdate()) {
|
||||
obs_data_apply(settings, oldSettings);
|
||||
else
|
||||
} else {
|
||||
obs_source_update(source, oldSettings);
|
||||
}
|
||||
|
||||
close();
|
||||
}
|
||||
@@ -348,8 +352,9 @@ void OBSBasicProperties::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
||||
{
|
||||
OBSBasicProperties *window = static_cast<OBSBasicProperties *>(data);
|
||||
|
||||
if (!window->source)
|
||||
if (!window->source) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sourceCX = max(obs_source_get_width(window->source), 1u);
|
||||
uint32_t sourceCY = max(obs_source_get_height(window->source), 1u);
|
||||
@@ -380,8 +385,9 @@ void OBSBasicProperties::DrawTransitionPreview(void *data, uint32_t cx, uint32_t
|
||||
{
|
||||
OBSBasicProperties *window = static_cast<OBSBasicProperties *>(data);
|
||||
|
||||
if (!window->sourceClone)
|
||||
if (!window->sourceClone) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t sourceCX = max(obs_source_get_width(window->sourceClone), 1u);
|
||||
uint32_t sourceCY = max(obs_source_get_height(window->sourceClone), 1u);
|
||||
@@ -430,9 +436,10 @@ void OBSBasicProperties::reject()
|
||||
void OBSBasicProperties::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QDialog::closeEvent(event);
|
||||
if (event->isAccepted())
|
||||
if (event->isAccepted()) {
|
||||
Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
bool OBSBasicProperties::nativeEvent(const QByteArray &, void *message, qintptr *)
|
||||
{
|
||||
@@ -481,8 +488,9 @@ bool OBSBasicProperties::ConfirmQuit()
|
||||
switch (button) {
|
||||
case QMessageBox::Save:
|
||||
acceptClicked = true;
|
||||
if (view->DeferUpdate())
|
||||
if (view->DeferUpdate()) {
|
||||
view->UpdateSettings();
|
||||
}
|
||||
// Do nothing because the settings are already updated
|
||||
break;
|
||||
case QMessageBox::Discard:
|
||||
|
||||
@@ -130,11 +130,12 @@ OBSBasicTransform::~OBSBasicTransform()
|
||||
};
|
||||
|
||||
std::string redo_data(obs_data_get_json(wrapper));
|
||||
if (undo_data.compare(redo_data) != 0)
|
||||
if (undo_data.compare(redo_data) != 0) {
|
||||
main->undo_s.add_action(
|
||||
QTStr("Undo.Transform").arg(obs_source_get_name(obs_scene_get_source(main->GetCurrentScene()))),
|
||||
undo_redo, undo_redo, undo_data, redo_data);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicTransform::setScene(OBSScene scene)
|
||||
{
|
||||
@@ -168,8 +169,9 @@ void OBSBasicTransform::setEnabled(bool enable)
|
||||
void OBSBasicTransform::setItemQt(OBSSceneItem newItem)
|
||||
{
|
||||
item = newItem;
|
||||
if (item)
|
||||
if (item) {
|
||||
refreshControls();
|
||||
}
|
||||
|
||||
bool enable = !!item && !obs_sceneitem_locked(item);
|
||||
setEnabled(enable);
|
||||
@@ -180,9 +182,10 @@ void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t *data)
|
||||
OBSBasicTransform *window = static_cast<OBSBasicTransform *>(param);
|
||||
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
if (item == window->item && !window->ignoreTransformSignal)
|
||||
if (item == window->item && !window->ignoreTransformSignal) {
|
||||
QMetaObject::invokeMethod(window, "refreshControls");
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
|
||||
{
|
||||
@@ -190,18 +193,20 @@ void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
|
||||
obs_scene_t *scene = (obs_scene_t *)calldata_ptr(data, "scene");
|
||||
obs_sceneitem_t *item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
if (item == window->item)
|
||||
if (item == window->item) {
|
||||
window->setItem(FindASelectedItem(scene));
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicTransform *window = static_cast<OBSBasicTransform *>(param);
|
||||
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
if (item != window->item)
|
||||
if (item != window->item) {
|
||||
window->setItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t *data)
|
||||
{
|
||||
@@ -237,8 +242,9 @@ static int alignToIndex(uint32_t align)
|
||||
{
|
||||
int index = 0;
|
||||
for (uint32_t curAlign : indexToAlign) {
|
||||
if (curAlign == align)
|
||||
if (curAlign == align) {
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -248,8 +254,9 @@ static int alignToIndex(uint32_t align)
|
||||
|
||||
void OBSBasicTransform::refreshControls()
|
||||
{
|
||||
if (!item)
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_transform_info oti;
|
||||
obs_sceneitem_crop crop;
|
||||
@@ -333,8 +340,9 @@ void OBSBasicTransform::onAlignChanged(int index)
|
||||
|
||||
void OBSBasicTransform::onBoundsType(int index)
|
||||
{
|
||||
if (index == -1)
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_bounds_type type = (obs_bounds_type)index;
|
||||
bool enable = (type != OBS_BOUNDS_NONE);
|
||||
@@ -405,8 +413,9 @@ void OBSBasicTransform::onBoundsType(int index)
|
||||
|
||||
void OBSBasicTransform::onControlChanged()
|
||||
{
|
||||
if (ignoreItemChange)
|
||||
if (ignoreItemChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_source_t *source = obs_sceneitem_get_source(item);
|
||||
uint32_t source_cx = obs_source_get_width(source);
|
||||
@@ -441,8 +450,9 @@ void OBSBasicTransform::onControlChanged()
|
||||
|
||||
void OBSBasicTransform::onCropChanged()
|
||||
{
|
||||
if (ignoreItemChange)
|
||||
if (ignoreItemChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_sceneitem_crop crop;
|
||||
crop.left = uint32_t(ui->cropLeft->value());
|
||||
@@ -457,8 +467,9 @@ void OBSBasicTransform::onCropChanged()
|
||||
|
||||
void OBSBasicTransform::onSceneChanged(QListWidgetItem *current, QListWidgetItem *)
|
||||
{
|
||||
if (!current)
|
||||
if (!current) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSScene scene = GetOBSRef<OBSScene>(current);
|
||||
this->setScene(scene);
|
||||
|
||||
@@ -48,9 +48,10 @@ void OBSBasicVCamConfig::OutputTypeChanged()
|
||||
for (char **temp = scenes; *temp; temp++) {
|
||||
list->addItem(*temp);
|
||||
|
||||
if (config.scene.compare(*temp) == 0)
|
||||
if (config.scene.compare(*temp) == 0) {
|
||||
list->setCurrentIndex(list->count() - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VCamOutputType::SourceOutput: {
|
||||
@@ -59,8 +60,9 @@ void OBSBasicVCamConfig::OutputTypeChanged()
|
||||
auto AddSource = [&](obs_source_t *source) {
|
||||
auto name = obs_source_get_name(source);
|
||||
|
||||
if (!(obs_source_get_output_flags(source) & OBS_SOURCE_VIDEO))
|
||||
if (!(obs_source_get_output_flags(source) & OBS_SOURCE_VIDEO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sources.push_back(name);
|
||||
};
|
||||
@@ -69,8 +71,9 @@ void OBSBasicVCamConfig::OutputTypeChanged()
|
||||
obs_enum_sources(
|
||||
[](void *data, obs_source_t *source) {
|
||||
auto &AddSource = *static_cast<AddSource_t *>(data);
|
||||
if (!obs_source_removed(source))
|
||||
if (!obs_source_removed(source)) {
|
||||
AddSource(source);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
static_cast<void *>(&AddSource));
|
||||
@@ -80,15 +83,17 @@ void OBSBasicVCamConfig::OutputTypeChanged()
|
||||
for (auto &&source : sources) {
|
||||
list->addItem(source.c_str());
|
||||
|
||||
if (config.source == source)
|
||||
if (config.source == source) {
|
||||
list->setCurrentIndex(list->count() - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vcamActive)
|
||||
if (!vcamActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
requireRestart = (activeType == VCamOutputType::ProgramView && type != VCamOutputType::ProgramView) ||
|
||||
(activeType != VCamOutputType::ProgramView && type == VCamOutputType::ProgramView);
|
||||
|
||||
@@ -95,8 +95,9 @@ void OBSLogViewer::AddLine(int type, const QString &str)
|
||||
QScrollBar *scroll = ui->textArea->verticalScrollBar();
|
||||
bool bottomScrolled = scroll->value() >= scroll->maximum() - 10;
|
||||
|
||||
if (bottomScrolled)
|
||||
if (bottomScrolled) {
|
||||
scroll->setValue(scroll->maximum());
|
||||
}
|
||||
|
||||
QTextDocument *doc = ui->textArea->document();
|
||||
QTextCursor cursor(doc);
|
||||
@@ -106,15 +107,17 @@ void OBSLogViewer::AddLine(int type, const QString &str)
|
||||
cursor.insertBlock();
|
||||
cursor.endEditBlock();
|
||||
|
||||
if (bottomScrolled)
|
||||
if (bottomScrolled) {
|
||||
scroll->setValue(scroll->maximum());
|
||||
}
|
||||
}
|
||||
|
||||
void OBSLogViewer::on_openButton_clicked()
|
||||
{
|
||||
char logDir[512];
|
||||
if (GetAppConfigPath(logDir, sizeof(logDir), "obs-studio/logs") <= 0)
|
||||
if (GetAppConfigPath(logDir, sizeof(logDir), "obs-studio/logs") <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *log = App()->GetCurrentLog();
|
||||
|
||||
|
||||
@@ -103,8 +103,9 @@ OBSRemux::OBSRemux(const char *path, QWidget *parent, bool autoRemux_)
|
||||
|
||||
bool OBSRemux::stopRemux()
|
||||
{
|
||||
if (!worker->isWorking)
|
||||
if (!worker->isWorking) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// By locking the worker thread's mutex, we ensure that its
|
||||
// update poll will be blocked as long as we're in here with
|
||||
@@ -190,9 +191,10 @@ void OBSRemux::dropEvent(QDropEvent *ev)
|
||||
|
||||
void OBSRemux::dragEnterEvent(QDragEnterEvent *ev)
|
||||
{
|
||||
if (ev->mimeData()->hasUrls() && !worker->isWorking)
|
||||
if (ev->mimeData()->hasUrls() && !worker->isWorking) {
|
||||
ev->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSRemux::beginRemux()
|
||||
{
|
||||
@@ -208,15 +210,18 @@ void OBSRemux::beginRemux()
|
||||
QString message = QTStr("Remux.FileExists");
|
||||
message += "\n\n";
|
||||
|
||||
for (QFileInfo fileInfo : overwriteFiles)
|
||||
for (QFileInfo fileInfo : overwriteFiles) {
|
||||
message += fileInfo.canonicalFilePath() + "\n";
|
||||
|
||||
if (OBSMessageBox::question(this, QTStr("Remux.FileExistsTitle"), message) != QMessageBox::Yes)
|
||||
proceedWithRemux = false;
|
||||
}
|
||||
|
||||
if (!proceedWithRemux)
|
||||
if (OBSMessageBox::question(this, QTStr("Remux.FileExistsTitle"), message) != QMessageBox::Yes) {
|
||||
proceedWithRemux = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!proceedWithRemux) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set all jobs to "pending" first.
|
||||
queueModel->beginProcessing();
|
||||
@@ -264,16 +269,18 @@ void OBSRemux::remuxNextEntry()
|
||||
|
||||
void OBSRemux::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (!stopRemux())
|
||||
if (!stopRemux()) {
|
||||
event->ignore();
|
||||
else
|
||||
} else {
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSRemux::reject()
|
||||
{
|
||||
if (!stopRemux())
|
||||
if (!stopRemux()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
@@ -171,11 +171,13 @@ OBSYoutubeActions::OBSYoutubeActions(QWidget *parent, Auth *auth, bool broadcast
|
||||
|
||||
connect(workerThread, &WorkerThread::failed, this, [&]() {
|
||||
auto last_error = apiYouTube->GetLastError();
|
||||
if (last_error.isEmpty())
|
||||
if (last_error.isEmpty()) {
|
||||
last_error = QTStr("YouTube.Actions.Error.YouTubeApi");
|
||||
}
|
||||
|
||||
if (!apiYouTube->GetTranslatedError(last_error))
|
||||
if (!apiYouTube->GetTranslatedError(last_error)) {
|
||||
last_error = QTStr("YouTube.Actions.Error.Text").arg(last_error);
|
||||
}
|
||||
|
||||
ShowErrorDialog(this, last_error);
|
||||
QDialog::reject();
|
||||
@@ -227,15 +229,17 @@ OBSYoutubeActions::OBSYoutubeActions(QWidget *parent, Auth *auth, bool broadcast
|
||||
});
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget(label);
|
||||
|
||||
if (selectedBroadcast == broadcast)
|
||||
if (selectedBroadcast == broadcast) {
|
||||
label->clicked();
|
||||
}
|
||||
});
|
||||
workerThread->start();
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
bool rememberSettings = config_get_bool(main->activeConfiguration, "YouTube", "RememberSettings");
|
||||
if (rememberSettings)
|
||||
if (rememberSettings) {
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
// Switch to events page and select readied broadcast once loaded
|
||||
if (broadcastReady) {
|
||||
@@ -253,9 +257,10 @@ OBSYoutubeActions::OBSYoutubeActions(QWidget *parent, Auth *auth, bool broadcast
|
||||
void OBSYoutubeActions::showEvent(QShowEvent *event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
if (thumbnailFile.isEmpty())
|
||||
if (thumbnailFile.isEmpty()) {
|
||||
ui->thumbnailPreview->setPixmap(GetPlaceholder().pixmap(QSize(16, 16)));
|
||||
}
|
||||
}
|
||||
|
||||
OBSYoutubeActions::~OBSYoutubeActions()
|
||||
{
|
||||
@@ -267,8 +272,9 @@ OBSYoutubeActions::~OBSYoutubeActions()
|
||||
|
||||
void WorkerThread::run()
|
||||
{
|
||||
if (!pending)
|
||||
if (!pending) {
|
||||
return;
|
||||
}
|
||||
json11::Json broadcasts;
|
||||
|
||||
for (QString broadcastStatus : {"active", "upcoming"}) {
|
||||
@@ -288,11 +294,13 @@ void WorkerThread::run()
|
||||
QString stream_id = QString::fromStdString(
|
||||
item["contentDetails"]["boundStreamId"].string_value());
|
||||
json11::Json stream;
|
||||
if (!apiYouTube->FindStream(stream_id, stream))
|
||||
if (!apiYouTube->FindStream(stream_id, stream)) {
|
||||
continue;
|
||||
if (stream["status"]["streamStatus"] == "active")
|
||||
}
|
||||
if (stream["status"]["streamStatus"] == "active") {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
QString title = QString::fromStdString(item["snippet"]["title"].string_value());
|
||||
QString scheduledStartTime =
|
||||
@@ -317,11 +325,12 @@ void WorkerThread::run()
|
||||
}
|
||||
|
||||
auto nextPageToken = broadcasts["nextPageToken"].string_value();
|
||||
if (nextPageToken.empty() || items.empty())
|
||||
if (nextPageToken.empty() || items.empty()) {
|
||||
break;
|
||||
else {
|
||||
if (!pending)
|
||||
} else {
|
||||
if (!pending) {
|
||||
return;
|
||||
}
|
||||
if (!apiYouTube->GetBroadcastsList(broadcasts, QString::fromStdString(nextPageToken),
|
||||
broadcastStatus)) {
|
||||
emit failed();
|
||||
@@ -420,8 +429,9 @@ bool OBSYoutubeActions::CreateEventAction(YoutubeApiWrappers *api, BroadcastDesc
|
||||
}
|
||||
|
||||
#ifdef YOUTUBE_ENABLED
|
||||
if (OBSBasic::Get()->GetYouTubeAppDock())
|
||||
if (OBSBasic::Get()->GetYouTubeAppDock()) {
|
||||
OBSBasic::Get()->GetYouTubeAppDock()->BroadcastCreated(broadcast.id.toStdString().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -461,14 +471,16 @@ bool OBSYoutubeActions::ChooseAnEventAction(YoutubeApiWrappers *api, StreamDescr
|
||||
}
|
||||
}
|
||||
|
||||
if (broadcastPrivacy != "private")
|
||||
if (broadcastPrivacy != "private") {
|
||||
apiYouTube->SetChatId(selectedBroadcast);
|
||||
else
|
||||
} else {
|
||||
apiYouTube->ResetChat();
|
||||
}
|
||||
|
||||
#ifdef YOUTUBE_ENABLED
|
||||
if (OBSBasic::Get()->GetYouTubeAppDock())
|
||||
if (OBSBasic::Get()->GetYouTubeAppDock()) {
|
||||
OBSBasic::Get()->GetYouTubeAppDock()->BroadcastSelected(selectedBroadcast.toStdString().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -503,8 +515,9 @@ void OBSYoutubeActions::InitBroadcast()
|
||||
ui->checkScheduledLater->isChecked());
|
||||
} else {
|
||||
success = this->ChooseAnEventAction(apiYouTube, stream);
|
||||
if (success)
|
||||
if (success) {
|
||||
broadcast.id = this->selectedBroadcast;
|
||||
}
|
||||
};
|
||||
QMetaObject::invokeMethod(&msgBox, "accept", Qt::QueuedConnection);
|
||||
};
|
||||
@@ -540,10 +553,12 @@ void OBSYoutubeActions::InitBroadcast()
|
||||
} else {
|
||||
// Fail.
|
||||
auto last_error = apiYouTube->GetLastError();
|
||||
if (last_error.isEmpty())
|
||||
if (last_error.isEmpty()) {
|
||||
last_error = QTStr("YouTube.Actions.Error.YouTubeApi");
|
||||
if (!apiYouTube->GetTranslatedError(last_error))
|
||||
}
|
||||
if (!apiYouTube->GetTranslatedError(last_error)) {
|
||||
last_error = QTStr("YouTube.Actions.Error.NoBroadcastCreated").arg(last_error);
|
||||
}
|
||||
|
||||
ShowErrorDialog(this, last_error);
|
||||
}
|
||||
@@ -566,8 +581,9 @@ void OBSYoutubeActions::ReadyBroadcast()
|
||||
ui->checkScheduledLater->isChecked(), true);
|
||||
} else {
|
||||
success = this->ChooseAnEventAction(apiYouTube, stream);
|
||||
if (success)
|
||||
if (success) {
|
||||
broadcast.id = this->selectedBroadcast;
|
||||
}
|
||||
};
|
||||
QMetaObject::invokeMethod(&msgBox, "accept", Qt::QueuedConnection);
|
||||
};
|
||||
@@ -583,10 +599,12 @@ void OBSYoutubeActions::ReadyBroadcast()
|
||||
} else {
|
||||
// Fail.
|
||||
auto last_error = apiYouTube->GetLastError();
|
||||
if (last_error.isEmpty())
|
||||
if (last_error.isEmpty()) {
|
||||
last_error = QTStr("YouTube.Actions.Error.YouTubeApi");
|
||||
if (!apiYouTube->GetTranslatedError(last_error))
|
||||
}
|
||||
if (!apiYouTube->GetTranslatedError(last_error)) {
|
||||
last_error = QTStr("YouTube.Actions.Error.NoBroadcastCreated").arg(last_error);
|
||||
}
|
||||
|
||||
ShowErrorDialog(this, last_error);
|
||||
}
|
||||
@@ -608,9 +626,10 @@ void OBSYoutubeActions::UiToBroadcast(BroadcastDescription &broadcast)
|
||||
broadcast.schedul_for_later = ui->checkScheduledLater->isChecked();
|
||||
broadcast.projection = ui->check360Video->isChecked() ? "360" : "rectangular";
|
||||
|
||||
if (ui->checkRememberSettings->isChecked())
|
||||
if (ui->checkRememberSettings->isChecked()) {
|
||||
SaveSettings(broadcast);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSYoutubeActions::SaveSettings(BroadcastDescription &broadcast)
|
||||
{
|
||||
@@ -657,10 +676,11 @@ void OBSYoutubeActions::LoadSettings()
|
||||
ui->checkDVR->setChecked(dvr);
|
||||
|
||||
bool forKids = config_get_bool(main->activeConfiguration, "YouTube", "MadeForKids");
|
||||
if (forKids)
|
||||
if (forKids) {
|
||||
ui->yesMakeForKids->setChecked(true);
|
||||
else
|
||||
} else {
|
||||
ui->notMakeForKids->setChecked(true);
|
||||
}
|
||||
|
||||
bool schedLater = config_get_bool(main->activeConfiguration, "YouTube", "ScheduleForLater");
|
||||
ui->checkScheduledLater->setChecked(schedLater);
|
||||
@@ -673,11 +693,12 @@ void OBSYoutubeActions::LoadSettings()
|
||||
|
||||
const char *projection = config_get_string(main->activeConfiguration, "YouTube", "Projection");
|
||||
if (projection && *projection) {
|
||||
if (strcmp(projection, "360") == 0)
|
||||
if (strcmp(projection, "360") == 0) {
|
||||
ui->check360Video->setChecked(true);
|
||||
else
|
||||
} else {
|
||||
ui->check360Video->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
const char *thumbFile = config_get_string(main->activeConfiguration, "YouTube", "ThumbnailFile");
|
||||
if (thumbFile && *thumbFile) {
|
||||
|
||||
@@ -41,8 +41,9 @@ YouTubeAppDock::YouTubeAppDock(const QString &title) : BrowserDock(title), dockB
|
||||
|
||||
bool YouTubeAppDock::IsYTServiceSelected()
|
||||
{
|
||||
if (!cef_js_avail)
|
||||
if (!cef_js_avail) {
|
||||
return false;
|
||||
}
|
||||
|
||||
obs_service_t *service_obj = OBSBasic::Get()->GetService();
|
||||
OBSDataAutoRelease settings = obs_service_get_settings(service_obj);
|
||||
@@ -74,9 +75,10 @@ void YouTubeAppDock::SettingsUpdated(bool cleanup)
|
||||
}
|
||||
}
|
||||
|
||||
if (ytservice)
|
||||
if (ytservice) {
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
std::string YouTubeAppDock::InitYTUserUrl()
|
||||
{
|
||||
@@ -124,14 +126,17 @@ void YouTubeAppDock::AddYouTubeAppDock()
|
||||
|
||||
void YouTubeAppDock::CreateBrowserWidget(const std::string &url)
|
||||
{
|
||||
if (dockBrowser)
|
||||
if (dockBrowser) {
|
||||
delete dockBrowser;
|
||||
}
|
||||
dockBrowser = cef->create_widget(this, url, panel_cookies);
|
||||
if (!dockBrowser)
|
||||
if (!dockBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (obs_browser_qcef_version() >= 1)
|
||||
if (obs_browser_qcef_version() >= 1) {
|
||||
dockBrowser->allowAllPopups(true);
|
||||
}
|
||||
|
||||
this->SetWidget(dockBrowser);
|
||||
|
||||
@@ -142,8 +147,9 @@ void YouTubeAppDock::CreateBrowserWidget(const std::string &url)
|
||||
|
||||
void YouTubeAppDock::SetVisibleYTAppDockInMenu(bool visible)
|
||||
{
|
||||
if (visible && toggleViewAction()->isVisible())
|
||||
if (visible && toggleViewAction()->isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleViewAction()->setVisible(visible);
|
||||
this->setVisible(visible);
|
||||
@@ -208,9 +214,10 @@ void YouTubeAppDock::IngestionStopped(const char *stream_id, streaming_mode_t mo
|
||||
|
||||
void YouTubeAppDock::showEvent(QShowEvent *)
|
||||
{
|
||||
if (!dockBrowser)
|
||||
if (!dockBrowser) {
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
void YouTubeAppDock::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
@@ -220,8 +227,9 @@ void YouTubeAppDock::closeEvent(QCloseEvent *event)
|
||||
|
||||
void YouTubeAppDock::DispatchYTEvent(const char *event, const char *video_id, streaming_mode_t mode)
|
||||
{
|
||||
if (!dockBrowser)
|
||||
if (!dockBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update channelId if empty:
|
||||
UpdateChannelId();
|
||||
@@ -395,26 +403,30 @@ YoutubeApiWrappers *YouTubeAppDock::GetYTApi()
|
||||
|
||||
void YouTubeAppDock::CleanupYouTubeUrls()
|
||||
{
|
||||
if (!cef_js_avail)
|
||||
if (!cef_js_avail) {
|
||||
return;
|
||||
}
|
||||
|
||||
static constexpr const char *YOUTUBE_VIDEO_URL = "://studio.youtube.com/video/";
|
||||
// remove legacy YouTube Browser Docks (once)
|
||||
|
||||
bool youtube_cleanup_done = config_get_bool(App()->GetUserConfig(), "General", "YtDockCleanupDone");
|
||||
|
||||
if (youtube_cleanup_done)
|
||||
if (youtube_cleanup_done) {
|
||||
return;
|
||||
}
|
||||
|
||||
config_set_bool(App()->GetUserConfig(), "General", "YtDockCleanupDone", true);
|
||||
|
||||
const char *jsonStr = config_get_string(App()->GetUserConfig(), "BasicWindow", "ExtraBrowserDocks");
|
||||
if (!jsonStr)
|
||||
if (!jsonStr) {
|
||||
return;
|
||||
}
|
||||
|
||||
json array = json::parse(jsonStr);
|
||||
if (!array.is_array())
|
||||
if (!array.is_array()) {
|
||||
return;
|
||||
}
|
||||
|
||||
json save_array;
|
||||
std::string removedYTUrl;
|
||||
|
||||
@@ -139,9 +139,10 @@ void ImporterEntryPathItemDelegate::handleBrowse(QWidget *container)
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
if (isSet)
|
||||
if (isSet) {
|
||||
emit commitData(container);
|
||||
}
|
||||
}
|
||||
|
||||
void ImporterEntryPathItemDelegate::handleClear(QWidget *container)
|
||||
{
|
||||
|
||||
@@ -37,10 +37,11 @@ QVariant ImporterModel::data(const QModelIndex &index, int role) const
|
||||
QVariant result = QVariant();
|
||||
|
||||
if (index.row() >= options.length()) {
|
||||
if (role == ImporterEntryRole::CheckEmpty)
|
||||
if (role == ImporterEntryRole::CheckEmpty) {
|
||||
result = true;
|
||||
else
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
} else if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case ImporterColumn::Path:
|
||||
@@ -59,11 +60,12 @@ QVariant ImporterModel::data(const QModelIndex &index, int role) const
|
||||
} else if (role == Qt::CheckStateRole) {
|
||||
switch (index.column()) {
|
||||
case ImporterColumn::Selected:
|
||||
if (options[index.row()].program != "")
|
||||
if (options[index.row()].program != "") {
|
||||
result = options[index.row()].selected ? Qt::Checked : Qt::Unchecked;
|
||||
else
|
||||
} else {
|
||||
result = Qt::Unchecked;
|
||||
}
|
||||
}
|
||||
} else if (role == ImporterEntryRole::CheckEmpty) {
|
||||
result = options[index.row()].empty;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,9 @@ OBSImporter::OBSImporter(QWidget *parent) : QDialog(parent), optionsModel(new Im
|
||||
bool autoSearch = config_get_bool(App()->GetUserConfig(), "General", "AutomaticCollectionSearch");
|
||||
|
||||
OBSImporterFiles f;
|
||||
if (autoSearch)
|
||||
if (autoSearch) {
|
||||
f = ImportersFindFiles();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < f.size(); i++) {
|
||||
QString path = f[i].c_str();
|
||||
@@ -125,9 +126,10 @@ void OBSImporter::dropEvent(QDropEvent *ev)
|
||||
|
||||
void OBSImporter::dragEnterEvent(QDragEnterEvent *ev)
|
||||
{
|
||||
if (ev->mimeData()->hasUrls())
|
||||
if (ev->mimeData()->hasUrls()) {
|
||||
ev->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSImporter::browseImport()
|
||||
{
|
||||
@@ -175,8 +177,9 @@ void OBSImporter::importCollections()
|
||||
for (int i = 0; i < optionsModel->rowCount() - 1; i++) {
|
||||
int selected = optionsModel->index(i, ImporterColumn::Selected).data(Qt::CheckStateRole).value<int>();
|
||||
|
||||
if (selected == Qt::Unchecked)
|
||||
if (selected == Qt::Unchecked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string pathStr = optionsModel->index(i, ImporterColumn::Path)
|
||||
.data(Qt::DisplayRole)
|
||||
|
||||
@@ -26,9 +26,10 @@ static bool source_name_exists(const Json::array &sources, const string &name)
|
||||
{
|
||||
for (size_t i = 0; i < sources.size(); i++) {
|
||||
Json source = sources[i];
|
||||
if (name == source["name"].string_value())
|
||||
if (name == source["name"].string_value()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -208,8 +209,9 @@ static Json::object translate_source(const Json &in, const Json &sources)
|
||||
|
||||
Json browser = Json::parse(browser_dec, err);
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
Json::object obj = browser.object_items();
|
||||
|
||||
@@ -277,8 +279,9 @@ static void translate_sc(const Json &in, Json &out)
|
||||
for (size_t i = 0; i < scenes.size(); i++) {
|
||||
Json in_scene = scenes[i];
|
||||
|
||||
if (first_name.empty())
|
||||
if (first_name.empty()) {
|
||||
first_name = in_scene["name"].string_value();
|
||||
}
|
||||
|
||||
Json::array items = Json::array{};
|
||||
|
||||
@@ -294,9 +297,10 @@ static void translate_sc(const Json &in, Json &out)
|
||||
|
||||
items.push_back(out_item);
|
||||
|
||||
if (out_source.find("preexist") == out_source.end())
|
||||
if (out_source.find("preexist") == out_source.end()) {
|
||||
out_sources.push_back(out_source);
|
||||
}
|
||||
}
|
||||
|
||||
out_sources.push_back(
|
||||
Json::object{{"id", "scene"},
|
||||
@@ -341,12 +345,14 @@ static void create_data_item(Json::object &out, const string &line)
|
||||
{
|
||||
size_t end_pos = line.find(':') - 1;
|
||||
|
||||
if (end_pos == string::npos)
|
||||
if (end_pos == string::npos) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t start_pos = 0;
|
||||
while (line[start_pos] == ' ')
|
||||
while (line[start_pos] == ' ') {
|
||||
start_pos++;
|
||||
}
|
||||
|
||||
string name = line.substr(start_pos, end_pos - start_pos);
|
||||
const char *c_name = name.c_str();
|
||||
@@ -404,12 +410,14 @@ static Json::array create_sources(Json::object &out, string &line, string &src)
|
||||
while (!line.empty() && line[l_len - 1] != '}') {
|
||||
size_t end_pos = line.find(':');
|
||||
|
||||
if (end_pos == string::npos)
|
||||
if (end_pos == string::npos) {
|
||||
return Json::array{};
|
||||
}
|
||||
|
||||
size_t start_pos = 0;
|
||||
while (line[start_pos] == ' ')
|
||||
while (line[start_pos] == ' ') {
|
||||
start_pos++;
|
||||
}
|
||||
|
||||
string name = line.substr(start_pos, end_pos - start_pos - 1);
|
||||
|
||||
@@ -423,8 +431,9 @@ static Json::array create_sources(Json::object &out, string &line, string &src)
|
||||
l_len = line.size();
|
||||
}
|
||||
|
||||
if (!out.empty())
|
||||
if (!out.empty()) {
|
||||
out["sources"] = res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -433,12 +442,14 @@ static Json::object create_object(Json::object &out, string &line, string &src)
|
||||
{
|
||||
size_t end_pos = line.find(':');
|
||||
|
||||
if (end_pos == string::npos)
|
||||
if (end_pos == string::npos) {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
size_t start_pos = 0;
|
||||
while (line[start_pos] == ' ')
|
||||
while (line[start_pos] == ' ') {
|
||||
start_pos++;
|
||||
}
|
||||
|
||||
string name = line.substr(start_pos, end_pos - start_pos - 1);
|
||||
|
||||
@@ -450,22 +461,25 @@ static Json::object create_object(Json::object &out, string &line, string &src)
|
||||
|
||||
while (!line.empty() && line[l_len] != '}') {
|
||||
start_pos = 0;
|
||||
while (line[start_pos] == ' ')
|
||||
while (line[start_pos] == ' ') {
|
||||
start_pos++;
|
||||
}
|
||||
|
||||
if (line.substr(start_pos, 7) == "sources")
|
||||
if (line.substr(start_pos, 7) == "sources") {
|
||||
create_sources(res, line, src);
|
||||
else if (line[l_len] == '{')
|
||||
} else if (line[l_len] == '{') {
|
||||
create_object(res, line, src);
|
||||
else
|
||||
} else {
|
||||
create_data_item(res, line);
|
||||
}
|
||||
|
||||
line = ReadLine(src);
|
||||
l_len = line.size() - 1;
|
||||
}
|
||||
|
||||
if (!out.empty())
|
||||
if (!out.empty()) {
|
||||
out[name] = res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -478,11 +492,13 @@ string ClassicImporter::Name(const string &path)
|
||||
int ClassicImporter::ImportScenes(const string &path, string &name, Json &res)
|
||||
{
|
||||
BPtr<char> file_data = os_quick_read_utf8_file(path.c_str());
|
||||
if (!file_data)
|
||||
if (!file_data) {
|
||||
return IMPORTER_FILE_WONT_OPEN;
|
||||
}
|
||||
|
||||
if (name.empty())
|
||||
if (name.empty()) {
|
||||
name = GetFilenameFromPath(path);
|
||||
}
|
||||
|
||||
Json::object data = Json::object{};
|
||||
data["name"] = name;
|
||||
@@ -514,13 +530,15 @@ bool ClassicImporter::Check(const string &path)
|
||||
{
|
||||
BPtr<char> file_data = os_quick_read_utf8_file(path.c_str());
|
||||
|
||||
if (!file_data)
|
||||
if (!file_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check = false;
|
||||
|
||||
if (strncmp(file_data, "scenes : {\r\n", 12) == 0)
|
||||
if (strncmp(file_data, "scenes : {\r\n", 12) == 0) {
|
||||
check = true;
|
||||
}
|
||||
|
||||
return check;
|
||||
}
|
||||
@@ -532,14 +550,16 @@ OBSImporterFiles ClassicImporter::FindFiles()
|
||||
#ifdef _WIN32
|
||||
char dst[512];
|
||||
int found = os_get_config_path(dst, 512, "OBS\\sceneCollection\\");
|
||||
if (found == -1)
|
||||
if (found == -1) {
|
||||
return res;
|
||||
}
|
||||
|
||||
os_dir_t *dir = os_opendir(dst);
|
||||
struct os_dirent *ent;
|
||||
while ((ent = os_readdir(dir)) != NULL) {
|
||||
if (ent->directory || *ent->d_name == '.')
|
||||
if (ent->directory || *ent->d_name == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = ent->d_name;
|
||||
size_t pos = name.find(".xconfig");
|
||||
|
||||
@@ -103,8 +103,9 @@ static inline std::string GetFilenameFromPath(const std::string &path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
size_t pos = path.find_last_of('\\');
|
||||
if (pos == -1 || pos < path.find_last_of('/'))
|
||||
if (pos == -1 || pos < path.find_last_of('/')) {
|
||||
pos = path.find_last_of('/');
|
||||
}
|
||||
#else
|
||||
size_t pos = path.find_last_of('/');
|
||||
#endif
|
||||
@@ -121,8 +122,9 @@ static inline std::string GetFolderFromPath(const std::string &path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
size_t pos = path.find_last_of('\\');
|
||||
if (pos == -1 || pos < path.find_last_of('/'))
|
||||
if (pos == -1 || pos < path.find_last_of('/')) {
|
||||
pos = path.find_last_of('/');
|
||||
}
|
||||
#else
|
||||
size_t pos = path.find_last_of('/');
|
||||
#endif
|
||||
@@ -147,14 +149,17 @@ static inline std::string ReadLine(std::string &str)
|
||||
|
||||
size_t pos = str.find('\n');
|
||||
|
||||
if (pos == std::string::npos)
|
||||
if (pos == std::string::npos) {
|
||||
pos = str.find(EOF);
|
||||
}
|
||||
|
||||
if (pos == std::string::npos)
|
||||
if (pos == std::string::npos) {
|
||||
pos = str.find('\0');
|
||||
}
|
||||
|
||||
if (pos == std::string::npos)
|
||||
if (pos == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string res = str.substr(0, pos);
|
||||
str = str.substr(pos + 1);
|
||||
|
||||
+24
-12
@@ -114,9 +114,10 @@ static bool source_name_exists(const Json::array &sources, const string &name)
|
||||
Json item = sources[i];
|
||||
string source_name = item["name"].string_value();
|
||||
|
||||
if (source_name == name)
|
||||
if (source_name == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -127,9 +128,10 @@ static string get_source_name_from_id(const Json &root, const Json::array &sourc
|
||||
Json item = sources[i];
|
||||
string source_id = item["sl_id"].string_value();
|
||||
|
||||
if (source_id == id)
|
||||
if (source_id == id) {
|
||||
return item["name"].string_value();
|
||||
}
|
||||
}
|
||||
|
||||
Json::array scene_arr = root["scenes"]["items"].array_items();
|
||||
|
||||
@@ -143,8 +145,9 @@ static string get_source_name_from_id(const Json &root, const Json::array &sourc
|
||||
int copy = 1;
|
||||
string out_name = name;
|
||||
|
||||
while (source_name_exists(sources, out_name))
|
||||
while (source_name_exists(sources, out_name)) {
|
||||
out_name = name + "(" + to_string(copy++) + ")";
|
||||
}
|
||||
|
||||
return out_name;
|
||||
}
|
||||
@@ -169,8 +172,9 @@ static void get_hotkey_bindings(Json::object &out_hotkeys, const Json &in_hotkey
|
||||
|
||||
string key = translate_key(binding["key"].string_value());
|
||||
|
||||
if (key == "IGNORE")
|
||||
if (key == "IGNORE") {
|
||||
continue;
|
||||
}
|
||||
|
||||
out_hotkey.push_back(Json::object{{"control", modifiers["ctrl"]},
|
||||
{"shift", modifiers["shift"]},
|
||||
@@ -285,8 +289,9 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
||||
|
||||
int copy = 1;
|
||||
string out_name = name;
|
||||
while (source_name_exists(out_sources, out_name))
|
||||
while (source_name_exists(out_sources, out_name)) {
|
||||
out_name = name + "(" + to_string(copy++) + ")";
|
||||
}
|
||||
|
||||
string sl_id = source["id"].string_value();
|
||||
|
||||
@@ -336,11 +341,13 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
||||
|
||||
int copy = 1;
|
||||
string out_name = name;
|
||||
while (source_name_exists(out_sources, out_name))
|
||||
while (source_name_exists(out_sources, out_name)) {
|
||||
out_name = name + "(" + to_string(copy++) + ")";
|
||||
}
|
||||
|
||||
if (scene_name.empty())
|
||||
if (scene_name.empty()) {
|
||||
scene_name = out_name;
|
||||
}
|
||||
|
||||
string sl_id = scene["id"].string_value();
|
||||
|
||||
@@ -368,8 +375,9 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
||||
string name = transition["name"].string_value();
|
||||
string id = transition["id"].string_value();
|
||||
|
||||
if (id == t_id)
|
||||
if (id == t_id) {
|
||||
transition_name = name;
|
||||
}
|
||||
|
||||
out_transitions.push_back(Json::object{{"id", transition["type"]},
|
||||
{"settings", in_settings},
|
||||
@@ -436,8 +444,9 @@ int SLImporter::ImportScenes(const string &path, string &name, Json &res)
|
||||
std::string err;
|
||||
Json data = Json::parse(file_data, err);
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return IMPORTER_ERROR_DURING_CONVERSION;
|
||||
}
|
||||
|
||||
string node_type = data["nodeType"].string_value();
|
||||
|
||||
@@ -473,10 +482,11 @@ bool SLImporter::Check(const string &path)
|
||||
if (!root.is_null()) {
|
||||
string node_type = root["nodeType"].string_value();
|
||||
|
||||
if (node_type == "RootNode")
|
||||
if (node_type == "RootNode") {
|
||||
check = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return check;
|
||||
}
|
||||
@@ -489,16 +499,18 @@ OBSImporterFiles SLImporter::FindFiles()
|
||||
|
||||
int found = os_get_config_path(dst, 512, "slobs-client/SceneCollections/");
|
||||
|
||||
if (found == -1)
|
||||
if (found == -1) {
|
||||
return res;
|
||||
}
|
||||
|
||||
os_dir_t *dir = os_opendir(dst);
|
||||
struct os_dirent *ent;
|
||||
while ((ent = os_readdir(dir)) != NULL) {
|
||||
string name = ent->d_name;
|
||||
|
||||
if (ent->directory || name[0] == '.' || name == "manifest.json")
|
||||
if (ent->directory || name[0] == '.' || name == "manifest.json") {
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t pos = name.find_last_of(".json");
|
||||
size_t end_pos = name.size() - 1;
|
||||
|
||||
@@ -151,14 +151,17 @@ static string CheckPath(const string &path, const string &rootDir)
|
||||
*absPath = 0;
|
||||
size_t len = os_get_abs_path((rootDir + path).c_str(), absPath, sizeof(absPath));
|
||||
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
return path;
|
||||
}
|
||||
|
||||
if (strstr(absPath, root) != absPath)
|
||||
if (strstr(absPath, root) != absPath) {
|
||||
return path;
|
||||
}
|
||||
|
||||
if (*(absPath + rootLen) != QDir::separator().toLatin1())
|
||||
if (*(absPath + rootLen) != QDir::separator().toLatin1()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return absPath;
|
||||
}
|
||||
@@ -172,8 +175,9 @@ void TranslatePaths(Json &res, const string &rootDir)
|
||||
Json val = it->second;
|
||||
|
||||
if (val.is_string()) {
|
||||
if (val.string_value().rfind("./", 0) != 0)
|
||||
if (val.string_value().rfind("./", 0) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out[it->first] = CheckPath(val.string_value(), rootDir);
|
||||
} else if (val.is_array() || val.is_object()) {
|
||||
@@ -190,8 +194,9 @@ void TranslatePaths(Json &res, const string &rootDir)
|
||||
Json val = out[i];
|
||||
|
||||
if (val.is_string()) {
|
||||
if (val.string_value().rfind("./", 0) != 0)
|
||||
if (val.string_value().rfind("./", 0) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out[i] = CheckPath(val.string_value(), rootDir);
|
||||
} else if (val.is_array() || val.is_object()) {
|
||||
@@ -210,20 +215,25 @@ bool StudioImporter::Check(const string &path)
|
||||
string err;
|
||||
Json collection = Json::parse(file_data, err);
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (collection.is_null())
|
||||
if (collection.is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (collection["sources"].is_null())
|
||||
if (collection["sources"].is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (collection["name"].is_null())
|
||||
if (collection["name"].is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (collection["current_scene"].is_null())
|
||||
if (collection["current_scene"].is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -242,18 +252,21 @@ string StudioImporter::Name(const string &path)
|
||||
|
||||
int StudioImporter::ImportScenes(const string &path, string &name, Json &res)
|
||||
{
|
||||
if (!os_file_exists(path.c_str()))
|
||||
if (!os_file_exists(path.c_str())) {
|
||||
return IMPORTER_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!Check(path.c_str()))
|
||||
if (!Check(path.c_str())) {
|
||||
return IMPORTER_FILE_NOT_RECOGNISED;
|
||||
}
|
||||
|
||||
BPtr<char> file_data = os_quick_read_utf8_file(path.c_str());
|
||||
string err;
|
||||
Json d = Json::parse(file_data, err);
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return IMPORTER_ERROR_DURING_CONVERSION;
|
||||
}
|
||||
|
||||
QDir dir(path.c_str());
|
||||
|
||||
@@ -262,10 +275,11 @@ int StudioImporter::ImportScenes(const string &path, string &name, Json &res)
|
||||
|
||||
Json::object obj = d.object_items();
|
||||
|
||||
if (name != "")
|
||||
if (name != "") {
|
||||
obj["name"] = name;
|
||||
else
|
||||
} else {
|
||||
obj["name"] = "OBS Studio Import";
|
||||
}
|
||||
|
||||
res = obj;
|
||||
|
||||
|
||||
@@ -27,16 +27,18 @@ static int hex_string_to_int(string str)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (str[0] == '#')
|
||||
if (str[0] == '#') {
|
||||
str = str.substr(1);
|
||||
}
|
||||
|
||||
for (size_t i = 0, l = str.size(); i < l; i++) {
|
||||
res *= 16;
|
||||
|
||||
if (str[0] >= '0' && str[0] <= '9')
|
||||
if (str[0] >= '0' && str[0] <= '9') {
|
||||
res += str[0] - '0';
|
||||
else
|
||||
} else {
|
||||
res += str[0] - 'A' + 10;
|
||||
}
|
||||
|
||||
str = str.substr(1);
|
||||
}
|
||||
@@ -53,24 +55,27 @@ static Json::object parse_text(QString &config)
|
||||
string err;
|
||||
Json data = Json::parse(config.toStdString(), err);
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
string outline = data["outline"].string_value();
|
||||
int out = 0;
|
||||
|
||||
if (outline == "thick")
|
||||
if (outline == "thick") {
|
||||
out = 20;
|
||||
else if (outline == "thicker")
|
||||
} else if (outline == "thicker") {
|
||||
out = 40;
|
||||
else if (outline == "thinner")
|
||||
} else if (outline == "thinner") {
|
||||
out = 5;
|
||||
else if (outline == "thin")
|
||||
} else if (outline == "thin") {
|
||||
out = 10;
|
||||
}
|
||||
|
||||
string valign = data["vertAlign"].string_value();
|
||||
if (valign == "middle")
|
||||
if (valign == "middle") {
|
||||
valign = "center";
|
||||
}
|
||||
|
||||
Json font = Json::object{{"face", data["fontStyle"]}, {"size", 200}};
|
||||
|
||||
@@ -96,8 +101,9 @@ static Json::array parse_playlist(QString &playlist)
|
||||
out.push_back(Json::object{{"value", path.toStdString()}});
|
||||
|
||||
int next = playlist.indexOf('|');
|
||||
if (next == -1)
|
||||
if (next == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
playlist = playlist.mid(next + 1);
|
||||
}
|
||||
@@ -114,8 +120,9 @@ static void parse_media_types(QDomNamedNodeMap &attr, Json::object &source, Json
|
||||
settings["playlist"] = parse_playlist(playlist);
|
||||
|
||||
QString end_op = attr.namedItem("OpWhenFinished").nodeValue();
|
||||
if (end_op == "2")
|
||||
if (end_op == "2") {
|
||||
settings["loop"] = true;
|
||||
}
|
||||
} else {
|
||||
QString url = attr.namedItem("item").nodeValue();
|
||||
int sep = url.indexOf("://");
|
||||
@@ -149,22 +156,25 @@ static void parse_media_types(QDomNamedNodeMap &attr, Json::object &source, Json
|
||||
static Json::object parse_slideshow(QString &config)
|
||||
{
|
||||
int start = config.indexOf("images\":[");
|
||||
if (start == -1)
|
||||
if (start == -1) {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
config = config.mid(start + 8);
|
||||
config.replace("\\\\", "/");
|
||||
|
||||
int end = config.indexOf(']');
|
||||
if (end == -1)
|
||||
if (end == -1) {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
string arr = config.left(end + 1).toStdString();
|
||||
string err;
|
||||
Json::array files = Json::parse(arr, err).array_items();
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
Json::array files_out = Json::array{};
|
||||
|
||||
@@ -178,8 +188,9 @@ static Json::object parse_slideshow(QString &config)
|
||||
|
||||
Json opt = Json::parse(options.toStdString(), err);
|
||||
|
||||
if (err != "")
|
||||
if (err != "") {
|
||||
return Json::object{};
|
||||
}
|
||||
|
||||
return Json::object{{"randomize", opt["random"]},
|
||||
{"slide_time", opt["delay"].number_value() * 1000 + 700},
|
||||
@@ -189,9 +200,10 @@ static Json::object parse_slideshow(QString &config)
|
||||
static bool source_name_exists(const string &name, const Json::array &sources)
|
||||
{
|
||||
for (size_t i = 0; i < sources.size(); i++) {
|
||||
if (sources.at(i)["name"].string_value() == name)
|
||||
if (sources.at(i)["name"].string_value() == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -199,9 +211,10 @@ static bool source_name_exists(const string &name, const Json::array &sources)
|
||||
static Json get_source_with_id(const string &src_id, const Json::array &sources)
|
||||
{
|
||||
for (size_t i = 0; i < sources.size(); i++) {
|
||||
if (sources.at(i)["src_id"].string_value() == src_id)
|
||||
if (sources.at(i)["src_id"].string_value() == src_id) {
|
||||
return sources.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -227,8 +240,9 @@ static void parse_items(QDomNode &item, Json::array &items, Json::array &sources
|
||||
}
|
||||
|
||||
name = attr.namedItem("cname").nodeValue().toStdString();
|
||||
if (name.empty() || name[0] == '\0')
|
||||
if (name.empty() || name[0] == '\0') {
|
||||
name = attr.namedItem("name").nodeValue().toStdString();
|
||||
}
|
||||
|
||||
temp_name = name;
|
||||
while (source_name_exists(temp_name, sources)) {
|
||||
@@ -394,8 +408,9 @@ static Json::object parse_scenes(QDomElement &scenes)
|
||||
QString name = attr.namedItem("name").nodeValue();
|
||||
QString id = attr.namedItem("id").nodeValue();
|
||||
|
||||
if (first.isEmpty())
|
||||
if (first.isEmpty()) {
|
||||
first = name;
|
||||
}
|
||||
|
||||
Json out = Json::object{{"id", "scene"},
|
||||
{"name", name.toStdString().c_str()},
|
||||
@@ -429,13 +444,15 @@ static Json::object parse_scenes(QDomElement &scenes)
|
||||
|
||||
int XSplitImporter::ImportScenes(const string &path, string &name, json11::Json &res)
|
||||
{
|
||||
if (name == "")
|
||||
if (name == "") {
|
||||
name = "XSplit Import";
|
||||
}
|
||||
|
||||
BPtr<char> file_data = os_quick_read_utf8_file(path.c_str());
|
||||
|
||||
if (!file_data)
|
||||
if (!file_data) {
|
||||
return IMPORTER_FILE_WONT_OPEN;
|
||||
}
|
||||
|
||||
QDomDocument doc;
|
||||
doc.setContent(QString(file_data));
|
||||
@@ -461,8 +478,9 @@ bool XSplitImporter::Check(const string &path)
|
||||
|
||||
BPtr<char> file_data = os_quick_read_utf8_file(path.c_str());
|
||||
|
||||
if (!file_data)
|
||||
if (!file_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string pos = file_data.Get();
|
||||
|
||||
@@ -488,8 +506,9 @@ OBSImporterFiles XSplitImporter::FindFiles()
|
||||
char dst[512];
|
||||
int found = os_get_program_data_path(dst, 512, "SplitMediaLabs\\XSplit\\Presentation2.0\\");
|
||||
|
||||
if (found == -1)
|
||||
if (found == -1) {
|
||||
return res;
|
||||
}
|
||||
|
||||
os_dir_t *dir = os_opendir(dst);
|
||||
struct os_dirent *ent;
|
||||
@@ -497,8 +516,9 @@ OBSImporterFiles XSplitImporter::FindFiles()
|
||||
while ((ent = os_readdir(dir)) != NULL) {
|
||||
string name = ent->d_name;
|
||||
|
||||
if (ent->directory || name[0] == '.')
|
||||
if (ent->directory || name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name == "Placements.bpres") {
|
||||
string str = dst + name;
|
||||
|
||||
@@ -54,8 +54,9 @@ void Auth::Load()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
const char *typeStr = config_get_string(main->Config(), "Auth", "Type");
|
||||
if (!typeStr)
|
||||
if (!typeStr) {
|
||||
typeStr = "";
|
||||
}
|
||||
|
||||
main->auth = Create(typeStr);
|
||||
if (main->auth) {
|
||||
|
||||
@@ -72,10 +72,11 @@ void AuthListener::NewConnection()
|
||||
if (match.hasMatch()) {
|
||||
if (state == match.captured("state")) {
|
||||
match = re_code.match(redirect);
|
||||
if (!match.hasMatch())
|
||||
if (!match.hasMatch()) {
|
||||
blog(LOG_DEBUG, "no 'code' "
|
||||
"in server "
|
||||
"redirect");
|
||||
}
|
||||
|
||||
code = match.captured("code");
|
||||
} else {
|
||||
|
||||
+19
-10
@@ -73,10 +73,12 @@ bool OAuth::LoadInternal()
|
||||
|
||||
bool OAuth::TokenExpired()
|
||||
{
|
||||
if (token.empty())
|
||||
if (token.empty()) {
|
||||
return true;
|
||||
if ((uint64_t)time(nullptr) > expire_time - 5)
|
||||
}
|
||||
if ((uint64_t)time(nullptr) > expire_time - 5) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -142,12 +144,14 @@ try {
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(func, QTStr("Auth.Authing.Title"), QTStr("Auth.Authing.Text").arg(service()));
|
||||
if (!success || output.empty())
|
||||
if (!success || output.empty()) {
|
||||
throw ErrorInfo("Failed to get token from remote", error);
|
||||
}
|
||||
|
||||
Json json = Json::parse(output, error);
|
||||
if (!error.empty())
|
||||
if (!error.empty()) {
|
||||
throw ErrorInfo("Failed to parse json", error);
|
||||
}
|
||||
|
||||
/* -------------------------- */
|
||||
/* error handling */
|
||||
@@ -158,23 +162,26 @@ try {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!error.empty())
|
||||
if (!error.empty()) {
|
||||
throw ErrorInfo(error, json["error_description"].string_value());
|
||||
}
|
||||
|
||||
/* -------------------------- */
|
||||
/* success! */
|
||||
|
||||
expire_time = (uint64_t)time(nullptr) + json["expires_in"].int_value();
|
||||
token = json["access_token"].string_value();
|
||||
if (token.empty())
|
||||
if (token.empty()) {
|
||||
throw ErrorInfo("Failed to get token from remote", error);
|
||||
}
|
||||
|
||||
if (!auth_code.empty()) {
|
||||
refresh_token = json["refresh_token"].string_value();
|
||||
if (refresh_token.empty())
|
||||
if (refresh_token.empty()) {
|
||||
throw ErrorInfo("Failed to get refresh token from "
|
||||
"remote",
|
||||
error);
|
||||
}
|
||||
|
||||
currentScopeVer = scope_ver;
|
||||
}
|
||||
@@ -195,8 +202,9 @@ try {
|
||||
|
||||
void OAuthStreamKey::OnStreamConfig()
|
||||
{
|
||||
if (key_.empty())
|
||||
if (key_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
obs_service_t *service = main->GetService();
|
||||
@@ -205,10 +213,11 @@ void OAuthStreamKey::OnStreamConfig()
|
||||
|
||||
bool bwtest = obs_data_get_bool(settings, "bwtest");
|
||||
|
||||
if (bwtest && strcmp(this->service(), "Twitch") == 0)
|
||||
if (bwtest && strcmp(this->service(), "Twitch") == 0) {
|
||||
obs_data_set_string(settings, "key", (key_ + "?bandwidthtest=true").c_str());
|
||||
else
|
||||
} else {
|
||||
obs_data_set_string(settings, "key", key_.c_str());
|
||||
}
|
||||
|
||||
obs_service_update(service, settings);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,9 @@ RestreamAuth::RestreamAuth(const Def &d) : OAuthStreamKey(d) {}
|
||||
|
||||
RestreamAuth::~RestreamAuth()
|
||||
{
|
||||
if (!uiLoaded)
|
||||
if (!uiLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
|
||||
@@ -49,12 +50,15 @@ try {
|
||||
std::string client_id = RESTREAM_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], RESTREAM_HASH);
|
||||
|
||||
if (!GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION))
|
||||
if (!GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION)) {
|
||||
return false;
|
||||
if (token.empty())
|
||||
}
|
||||
if (token.empty()) {
|
||||
return false;
|
||||
if (!key_.empty())
|
||||
}
|
||||
if (!key_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string auth;
|
||||
auth += "Authorization: Bearer ";
|
||||
@@ -76,16 +80,19 @@ try {
|
||||
|
||||
ExecThreadedWithoutBlocking(func, QTStr("Auth.LoadingChannel.Title"),
|
||||
QTStr("Auth.LoadingChannel.Text").arg(service()));
|
||||
if (!success || output.empty())
|
||||
if (!success || output.empty()) {
|
||||
throw ErrorInfo("Failed to get stream key from remote", error);
|
||||
}
|
||||
|
||||
json = Json::parse(output, error);
|
||||
if (!error.empty())
|
||||
if (!error.empty()) {
|
||||
throw ErrorInfo("Failed to parse json", error);
|
||||
}
|
||||
|
||||
error = json["error"].string_value();
|
||||
if (!error.empty())
|
||||
if (!error.empty()) {
|
||||
throw ErrorInfo(error, json["error_description"].string_value());
|
||||
}
|
||||
|
||||
key_ = json["streamKey"].string_value();
|
||||
|
||||
@@ -121,12 +128,15 @@ bool RestreamAuth::LoadInternal()
|
||||
|
||||
void RestreamAuth::LoadUI()
|
||||
{
|
||||
if (!cef)
|
||||
if (!cef) {
|
||||
return;
|
||||
if (uiLoaded)
|
||||
}
|
||||
if (uiLoaded) {
|
||||
return;
|
||||
if (!GetChannelInfo())
|
||||
}
|
||||
if (!GetChannelInfo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic::InitBrowserPanelSafeBlock();
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
@@ -266,8 +276,9 @@ static void DeleteCookies()
|
||||
void RegisterRestreamAuth()
|
||||
{
|
||||
#if !defined(__APPLE__) && !defined(_WIN32)
|
||||
if (QApplication::platformName().contains("wayland"))
|
||||
if (QApplication::platformName().contains("wayland")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OAuth::RegisterOAuth(restreamDef, CreateRestreamAuth, RestreamAuth::Login, DeleteCookies);
|
||||
|
||||
@@ -33,8 +33,9 @@ static Auth::Def twitchDef = {"Twitch", Auth::Type::OAuth_StreamKey};
|
||||
|
||||
TwitchAuth::TwitchAuth(const Def &d) : OAuthStreamKey(d)
|
||||
{
|
||||
if (!cef)
|
||||
if (!cef) {
|
||||
return;
|
||||
}
|
||||
|
||||
cef->add_popup_whitelist_url("https://twitch.tv/popout/frankerfacez/chat?ffz-settings", this);
|
||||
|
||||
@@ -48,8 +49,9 @@ TwitchAuth::TwitchAuth(const Def &d) : OAuthStreamKey(d)
|
||||
|
||||
TwitchAuth::~TwitchAuth()
|
||||
{
|
||||
if (!uiLoaded)
|
||||
if (!uiLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
|
||||
@@ -95,16 +97,19 @@ bool TwitchAuth::MakeApiRequest(const char *path, Json &json_out)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!success || output.empty())
|
||||
if (!success || output.empty()) {
|
||||
throw ErrorInfo("Failed to get text from remote", error);
|
||||
}
|
||||
|
||||
json_out = Json::parse(output, error);
|
||||
if (!error.empty())
|
||||
if (!error.empty()) {
|
||||
throw ErrorInfo("Failed to parse json", error);
|
||||
}
|
||||
|
||||
error = json_out["error"].string_value();
|
||||
if (!error.empty())
|
||||
if (!error.empty()) {
|
||||
throw ErrorInfo(error, json_out["message"].string_value());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -114,25 +119,30 @@ try {
|
||||
std::string client_id = TWITCH_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], TWITCH_HASH);
|
||||
|
||||
if (!GetToken(TWITCH_TOKEN_URL, client_id, TWITCH_SCOPE_VERSION))
|
||||
if (!GetToken(TWITCH_TOKEN_URL, client_id, TWITCH_SCOPE_VERSION)) {
|
||||
return false;
|
||||
if (token.empty())
|
||||
}
|
||||
if (token.empty()) {
|
||||
return false;
|
||||
if (!key_.empty())
|
||||
}
|
||||
if (!key_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Json json;
|
||||
bool success = MakeApiRequest("users", json);
|
||||
|
||||
if (!success)
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = json["data"][0]["login"].string_value();
|
||||
|
||||
std::string path = "streams/key?broadcaster_id=" + json["data"][0]["id"].string_value();
|
||||
success = MakeApiRequest(path.c_str(), json);
|
||||
if (!success)
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
key_ = json["data"][0]["stream_key"].string_value();
|
||||
|
||||
@@ -167,8 +177,9 @@ static inline std::string get_config_str(OBSBasic *main, const char *section, co
|
||||
|
||||
bool TwitchAuth::LoadInternal()
|
||||
{
|
||||
if (!cef)
|
||||
if (!cef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
name = get_config_str(main, service(), "Name");
|
||||
@@ -197,12 +208,15 @@ static const char *referrer_script2 = "'; }});";
|
||||
|
||||
void TwitchAuth::LoadUI()
|
||||
{
|
||||
if (!cef)
|
||||
if (!cef) {
|
||||
return;
|
||||
if (uiLoaded)
|
||||
}
|
||||
if (uiLoaded) {
|
||||
return;
|
||||
if (!GetChannelInfo())
|
||||
}
|
||||
if (!GetChannelInfo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic::InitBrowserPanelSafeBlock();
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
@@ -253,11 +267,13 @@ void TwitchAuth::LoadUI()
|
||||
|
||||
const int twAddonChoice = config_get_int(main->Config(), service(), "AddonChoice");
|
||||
if (twAddonChoice) {
|
||||
if (twAddonChoice & 0x1)
|
||||
if (twAddonChoice & 0x1) {
|
||||
script += bttv_script;
|
||||
if (twAddonChoice & 0x2)
|
||||
}
|
||||
if (twAddonChoice & 0x2) {
|
||||
script += ffz_script;
|
||||
}
|
||||
}
|
||||
|
||||
browser->setStartupScript(script);
|
||||
|
||||
@@ -305,11 +321,13 @@ void TwitchAuth::LoadSecondaryUIPanes()
|
||||
|
||||
const int twAddonChoice = config_get_int(main->Config(), service(), "AddonChoice");
|
||||
if (twAddonChoice) {
|
||||
if (twAddonChoice & 0x1)
|
||||
if (twAddonChoice & 0x1) {
|
||||
script += bttv_script;
|
||||
if (twAddonChoice & 0x2)
|
||||
}
|
||||
if (twAddonChoice & 0x2) {
|
||||
script += ffz_script;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------- */
|
||||
|
||||
@@ -396,10 +414,11 @@ void TwitchAuth::LoadSecondaryUIPanes()
|
||||
const char *dockStateStr = config_get_string(main->Config(), service(), "DockState");
|
||||
QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
|
||||
if (main->isVisible() || !main->isMaximized())
|
||||
if (main->isVisible() || !main->isMaximized()) {
|
||||
main->restoreState(dockState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Twitch.tv has an OAuth for itself. If we try to load multiple panel pages
|
||||
* at once before it's OAuth'ed itself, they will all try to perform the auth
|
||||
@@ -474,15 +493,17 @@ static std::shared_ptr<Auth> CreateTwitchAuth()
|
||||
|
||||
static void DeleteCookies()
|
||||
{
|
||||
if (panel_cookies)
|
||||
if (panel_cookies) {
|
||||
panel_cookies->DeleteCookies("twitch.tv", std::string());
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterTwitchAuth()
|
||||
{
|
||||
#if !defined(__APPLE__) && !defined(_WIN32)
|
||||
if (QApplication::platformName().contains("wayland"))
|
||||
if (QApplication::platformName().contains("wayland")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
OAuth::RegisterOAuth(twitchDef, CreateTwitchAuth, TwitchAuth::Login, DeleteCookies);
|
||||
|
||||
@@ -58,8 +58,9 @@ YoutubeAuth::YoutubeAuth(const Def &d) : OAuthStreamKey(d), section(SECTION_NAME
|
||||
|
||||
YoutubeAuth::~YoutubeAuth()
|
||||
{
|
||||
if (!uiLoaded)
|
||||
if (!uiLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
@@ -107,12 +108,14 @@ bool YoutubeAuth::LoadInternal()
|
||||
|
||||
void YoutubeAuth::LoadUI()
|
||||
{
|
||||
if (uiLoaded)
|
||||
if (uiLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
if (!cef)
|
||||
if (!cef) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSBasic::InitBrowserPanelSafeBlock();
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
@@ -191,8 +194,9 @@ QString YoutubeAuth::GenerateState()
|
||||
QRandomGenerator *rng = QRandomGenerator::system();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < YOUTUBE_API_STATE_LENGTH; i++)
|
||||
for (i = 0; i < YOUTUBE_API_STATE_LENGTH; i++) {
|
||||
state[i] = allowedChars[rng->bounded(0, allowedCount)];
|
||||
}
|
||||
state[i] = 0;
|
||||
|
||||
return state;
|
||||
@@ -285,8 +289,9 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner, const std::string &serv
|
||||
dlg.exec();
|
||||
#endif
|
||||
|
||||
if (dlg.result() == QMessageBox::Cancel || dlg.result() == QDialog::Rejected)
|
||||
if (dlg.result() == QMessageBox::Cancel || dlg.result() == QDialog::Rejected) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!auth->GetToken(YOUTUBE_TOKEN_URL, clientid, secret, QT_TO_UTF8(redirect_uri), YOUTUBE_SCOPE_VERSION,
|
||||
QT_TO_UTF8(auth_code), true)) {
|
||||
@@ -297,8 +302,9 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner, const std::string &serv
|
||||
config_remove_value(config, "YouTube", "ChannelName");
|
||||
|
||||
ChannelDescription cd;
|
||||
if (auth->GetChannelDescription(cd))
|
||||
if (auth->GetChannelDescription(cd)) {
|
||||
config_set_string(config, "YouTube", "ChannelName", QT_TO_UTF8(cd.title));
|
||||
}
|
||||
|
||||
config_save_safe(config, "tmp", nullptr);
|
||||
return auth;
|
||||
|
||||
+72
-36
@@ -127,8 +127,9 @@ static inline void LogStringChunk(fstream &logFile, char *str, int log_level)
|
||||
|
||||
while (*nextLine) {
|
||||
char *nextLine = strchr(str, '\n');
|
||||
if (!nextLine)
|
||||
if (!nextLine) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextLine != str && nextLine[-1] == '\r') {
|
||||
nextLine[-1] = 0;
|
||||
@@ -150,8 +151,9 @@ static inline void LogStringChunk(fstream &logFile, char *str, int log_level)
|
||||
static inline int sum_chars(const char *str)
|
||||
{
|
||||
int val = 0;
|
||||
for (; *str != 0; str++)
|
||||
for (; *str != 0; str++) {
|
||||
val += *str;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
@@ -228,13 +230,15 @@ static void do_log(int log_level, const char *msg, va_list args, void *param)
|
||||
#if !defined(_WIN32) && !defined(_DEBUG)
|
||||
def_log_handler(log_level, msg, args2, nullptr);
|
||||
#endif
|
||||
if (!too_many_repeated_entries(logFile, msg, str))
|
||||
if (!too_many_repeated_entries(logFile, msg, str)) {
|
||||
LogStringChunk(logFile, str, log_level);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(OBS_DEBUGBREAK_ON_ERROR)
|
||||
if (log_level <= LOG_ERROR && IsDebuggerPresent())
|
||||
if (log_level <= LOG_ERROR && IsDebuggerPresent()) {
|
||||
__debugbreak();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -245,10 +249,12 @@ static void do_log(int log_level, const char *msg, va_list args, void *param)
|
||||
static bool get_token(lexer *lex, string &str, base_token_type type)
|
||||
{
|
||||
base_token token;
|
||||
if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE))
|
||||
if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE)) {
|
||||
return false;
|
||||
if (token.type != type)
|
||||
}
|
||||
if (token.type != type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
str.assign(token.text.array, token.text.len);
|
||||
return true;
|
||||
@@ -257,10 +263,12 @@ static bool get_token(lexer *lex, string &str, base_token_type type)
|
||||
static bool expect_token(lexer *lex, const char *str, base_token_type type)
|
||||
{
|
||||
base_token token;
|
||||
if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE))
|
||||
if (!lexer_getbasetoken(lex, &token, IGNORE_WHITESPACE)) {
|
||||
return false;
|
||||
if (token.type != type)
|
||||
}
|
||||
if (token.type != type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strref_cmp(&token.text, str) == 0;
|
||||
}
|
||||
@@ -274,30 +282,41 @@ static uint64_t convert_log_name(bool has_prefix, const char *name)
|
||||
|
||||
if (has_prefix) {
|
||||
string temp;
|
||||
if (!get_token(lex, temp, BASETOKEN_ALPHA))
|
||||
if (!get_token(lex, temp, BASETOKEN_ALPHA)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!get_token(lex, year, BASETOKEN_DIGIT))
|
||||
if (!get_token(lex, year, BASETOKEN_DIGIT)) {
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
}
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) {
|
||||
return 0;
|
||||
if (!get_token(lex, month, BASETOKEN_DIGIT))
|
||||
}
|
||||
if (!get_token(lex, month, BASETOKEN_DIGIT)) {
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
}
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) {
|
||||
return 0;
|
||||
if (!get_token(lex, day, BASETOKEN_DIGIT))
|
||||
}
|
||||
if (!get_token(lex, day, BASETOKEN_DIGIT)) {
|
||||
return 0;
|
||||
if (!get_token(lex, hour, BASETOKEN_DIGIT))
|
||||
}
|
||||
if (!get_token(lex, hour, BASETOKEN_DIGIT)) {
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
}
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) {
|
||||
return 0;
|
||||
if (!get_token(lex, minute, BASETOKEN_DIGIT))
|
||||
}
|
||||
if (!get_token(lex, minute, BASETOKEN_DIGIT)) {
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
}
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) {
|
||||
return 0;
|
||||
if (!get_token(lex, second, BASETOKEN_DIGIT))
|
||||
}
|
||||
if (!get_token(lex, second, BASETOKEN_DIGIT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
stringstream timestring;
|
||||
timestring << year << month << day << hour << minute << second;
|
||||
@@ -318,8 +337,9 @@ static void delete_oldest_file(bool has_prefix, const char *location)
|
||||
unsigned int count = 0;
|
||||
|
||||
while ((entry = os_readdir(dir)) != NULL) {
|
||||
if (entry->directory || *entry->d_name == '.')
|
||||
if (entry->directory || *entry->d_name == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t ts = convert_log_name(has_prefix, entry->d_name);
|
||||
|
||||
@@ -353,8 +373,9 @@ static void get_last_log(bool has_prefix, const char *subdir_to_use, std::string
|
||||
|
||||
if (dir) {
|
||||
while ((entry = os_readdir(dir)) != NULL) {
|
||||
if (entry->directory || *entry->d_name == '.')
|
||||
if (entry->directory || *entry->d_name == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t ts = convert_log_name(has_prefix, entry->d_name);
|
||||
|
||||
@@ -419,12 +440,14 @@ ProfilerSnapshot GetSnapshot()
|
||||
|
||||
static void SaveProfilerData(const ProfilerSnapshot &snap)
|
||||
{
|
||||
if (currentLogFile.empty())
|
||||
if (currentLogFile.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto pos = currentLogFile.rfind('.');
|
||||
if (pos == currentLogFile.npos)
|
||||
if (pos == currentLogFile.npos) {
|
||||
return;
|
||||
}
|
||||
|
||||
#define LITERAL_SIZE(x) x, (sizeof(x) - 1)
|
||||
ostringstream dst;
|
||||
@@ -434,9 +457,10 @@ static void SaveProfilerData(const ProfilerSnapshot &snap)
|
||||
#undef LITERAL_SIZE
|
||||
|
||||
BPtr<char> path = GetAppConfigPathPtr(dst.str().c_str());
|
||||
if (!profiler_snapshot_dump_csv_gz(snap.get(), path))
|
||||
if (!profiler_snapshot_dump_csv_gz(snap.get(), path)) {
|
||||
blog(LOG_WARNING, "Could not save profiler data to '%s'", static_cast<const char *>(path));
|
||||
}
|
||||
}
|
||||
|
||||
static auto ProfilerFree = [](void *) {
|
||||
profiler_stop();
|
||||
@@ -453,8 +477,9 @@ static auto ProfilerFree = [](void *) {
|
||||
|
||||
QAccessibleInterface *accessibleFactory(const QString &classname, QObject *object)
|
||||
{
|
||||
if (classname == QLatin1String("VolumeSlider") && object && object->isWidgetType())
|
||||
if (classname == QLatin1String("VolumeSlider") && object && object->isWidgetType()) {
|
||||
return new VolumeAccessibleInterface(static_cast<QWidget *>(object));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -495,8 +520,9 @@ static int run_program(fstream &logFile, int argc, char *argv[])
|
||||
* crashes loading saved geometry. Just turn off this theme and let users complain OBS
|
||||
* looks ugly instead of crashing. */
|
||||
const char *platform_theme = getenv("QT_QPA_PLATFORMTHEME");
|
||||
if (platform_theme && strcmp(platform_theme, "qt5ct") == 0)
|
||||
if (platform_theme && strcmp(platform_theme, "qt5ct") == 0) {
|
||||
unsetenv("QT_QPA_PLATFORMTHEME");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* NOTE: This disables an optimisation in Qt that attempts to determine if
|
||||
@@ -547,8 +573,9 @@ static int run_program(fstream &logFile, int argc, char *argv[])
|
||||
cancel_launch = mb.clickedButton() == cancelButton;
|
||||
}
|
||||
|
||||
if (cancel_launch)
|
||||
if (cancel_launch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!created_log) {
|
||||
create_log_file(logFile);
|
||||
@@ -587,8 +614,9 @@ static int run_program(fstream &logFile, int argc, char *argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!created_log)
|
||||
if (!created_log) {
|
||||
create_log_file(logFile);
|
||||
}
|
||||
|
||||
program.checkForUncleanShutdown();
|
||||
|
||||
@@ -640,9 +668,10 @@ static int run_program(fstream &logFile, int argc, char *argv[])
|
||||
mb.setDefaultButton(closeButton);
|
||||
|
||||
mb.exec();
|
||||
if (mb.clickedButton() == closeButton)
|
||||
if (mb.clickedButton() == closeButton) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (argc > 1) {
|
||||
@@ -654,8 +683,9 @@ static int run_program(fstream &logFile, int argc, char *argv[])
|
||||
blog(LOG_INFO, "Command Line Arguments: %s", stor.str().c_str());
|
||||
}
|
||||
|
||||
if (!program.OBSInit())
|
||||
if (!program.OBSInit()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
prof.Stop();
|
||||
|
||||
@@ -833,11 +863,13 @@ static constexpr char vcRunInstallerUrl[] = "https://obsproject.com/visual-studi
|
||||
static bool vc_runtime_outdated()
|
||||
{
|
||||
win_version_info ver;
|
||||
if (!get_dll_ver(L"msvcp140.dll", &ver))
|
||||
if (!get_dll_ver(L"msvcp140.dll", &ver)) {
|
||||
return true;
|
||||
}
|
||||
/* Major is always 14 (hence 140.dll), so we only care about minor. */
|
||||
if (ver.minor >= 40)
|
||||
if (ver.minor >= 40) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int choice = MessageBoxA(NULL, vcRunErrorMsg, vcRunErrorTitle, MB_OKCANCEL | MB_ICONERROR | MB_TASKMODAL);
|
||||
if (choice == IDOK) {
|
||||
@@ -907,8 +939,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
#ifdef _WIN32
|
||||
// Abort as early as possible if MSVC runtime is outdated
|
||||
if (vc_runtime_outdated())
|
||||
if (vc_runtime_outdated()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Try to keep this as early as possible
|
||||
install_dll_blocklist_hook();
|
||||
@@ -981,16 +1014,19 @@ int main(int argc, char *argv[])
|
||||
opt_start_virtualcam = true;
|
||||
|
||||
} else if (arg_is(argv[i], "--collection", nullptr)) {
|
||||
if (++i < argc)
|
||||
if (++i < argc) {
|
||||
opt_starting_collection = argv[i];
|
||||
}
|
||||
|
||||
} else if (arg_is(argv[i], "--profile", nullptr)) {
|
||||
if (++i < argc)
|
||||
if (++i < argc) {
|
||||
opt_starting_profile = argv[i];
|
||||
}
|
||||
|
||||
} else if (arg_is(argv[i], "--scene", nullptr)) {
|
||||
if (++i < argc)
|
||||
if (++i < argc) {
|
||||
opt_starting_scene = argv[i];
|
||||
}
|
||||
|
||||
} else if (arg_is(argv[i], "--minimize-to-tray", nullptr)) {
|
||||
opt_minimize_tray = true;
|
||||
|
||||
@@ -39,8 +39,9 @@ void addModuleToPluginManagerImpl(void *param, obs_module_t *newModule)
|
||||
std::string moduleName = obs_get_module_file_name(newModule);
|
||||
moduleName = moduleName.substr(0, moduleName.rfind("."));
|
||||
|
||||
if (!obs_get_module_allow_disable(moduleName.c_str()))
|
||||
if (!obs_get_module_allow_disable(moduleName.c_str())) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *display_name = obs_get_module_name(newModule);
|
||||
std::string module_name = moduleName;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -181,8 +181,9 @@ void OBSBasicSettings::on_choose1_clicked()
|
||||
{
|
||||
QColor color = GetColor(selectRed, QTStr("Basic.Settings.Accessibility.ColorOverrides.SelectRed"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectRed = color_to_int(color);
|
||||
|
||||
@@ -200,8 +201,9 @@ void OBSBasicSettings::on_choose2_clicked()
|
||||
{
|
||||
QColor color = GetColor(selectGreen, QTStr("Basic.Settings.Accessibility.ColorOverrides.SelectGreen"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectGreen = color_to_int(color);
|
||||
|
||||
@@ -219,8 +221,9 @@ void OBSBasicSettings::on_choose3_clicked()
|
||||
{
|
||||
QColor color = GetColor(selectBlue, QTStr("Basic.Settings.Accessibility.ColorOverrides.SelectBlue"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectBlue = color_to_int(color);
|
||||
|
||||
@@ -238,8 +241,9 @@ void OBSBasicSettings::on_choose4_clicked()
|
||||
{
|
||||
QColor color = GetColor(mixerGreen, QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerGreen"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mixerGreen = color_to_int(color);
|
||||
|
||||
@@ -257,8 +261,9 @@ void OBSBasicSettings::on_choose5_clicked()
|
||||
{
|
||||
QColor color = GetColor(mixerYellow, QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerYellow"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mixerYellow = color_to_int(color);
|
||||
|
||||
@@ -276,8 +281,9 @@ void OBSBasicSettings::on_choose6_clicked()
|
||||
{
|
||||
QColor color = GetColor(mixerRed, QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerRed"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mixerRed = color_to_int(color);
|
||||
|
||||
@@ -296,8 +302,9 @@ void OBSBasicSettings::on_choose7_clicked()
|
||||
QColor color =
|
||||
GetColor(mixerGreenActive, QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerGreenActive"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mixerGreenActive = color_to_int(color);
|
||||
|
||||
@@ -316,8 +323,9 @@ void OBSBasicSettings::on_choose8_clicked()
|
||||
QColor color =
|
||||
GetColor(mixerYellowActive, QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerYellowActive"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mixerYellowActive = color_to_int(color);
|
||||
|
||||
@@ -335,8 +343,9 @@ void OBSBasicSettings::on_choose9_clicked()
|
||||
{
|
||||
QColor color = GetColor(mixerRedActive, QTStr("Basic.Settings.Accessibility.ColorOverrides.MixerRedActive"));
|
||||
|
||||
if (!color.isValid())
|
||||
if (!color.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mixerRedActive = color_to_int(color);
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@ void OBSBasicSettings::InitAppearancePage()
|
||||
}
|
||||
|
||||
int idx = ui->theme->findData(currentBaseTheme);
|
||||
if (idx != -1)
|
||||
if (idx != -1) {
|
||||
ui->theme->setCurrentIndex(idx);
|
||||
}
|
||||
|
||||
ui->themeVariant->setPlaceholderText(QTStr("Basic.Settings.Appearance.General.NoVariant"));
|
||||
|
||||
@@ -41,8 +42,9 @@ void OBSBasicSettings::LoadThemeList(bool reload)
|
||||
|
||||
/* Nothing to do if current and last base theme were the same */
|
||||
const QString baseThemeId = ui->theme->currentData().toString();
|
||||
if (reload && baseThemeId == currentBaseTheme)
|
||||
if (reload && baseThemeId == currentBaseTheme) {
|
||||
return;
|
||||
}
|
||||
|
||||
ui->themeVariant->blockSignals(true);
|
||||
ui->themeVariant->clear();
|
||||
@@ -57,20 +59,24 @@ void OBSBasicSettings::LoadThemeList(bool reload)
|
||||
|
||||
for (const OBSTheme &theme : themes) {
|
||||
/* Skip non-visible themes */
|
||||
if (!theme.isVisible || theme.isHighContrast)
|
||||
if (!theme.isVisible || theme.isHighContrast) {
|
||||
continue;
|
||||
}
|
||||
/* Skip non-child themes */
|
||||
if (theme.isBaseTheme || theme.parent != baseThemeId)
|
||||
if (theme.isBaseTheme || theme.parent != baseThemeId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui->themeVariant->addItem(theme.name, theme.id);
|
||||
if (baseTheme && theme.filename == baseTheme->filename)
|
||||
if (baseTheme && theme.filename == baseTheme->filename) {
|
||||
defaultVariant = theme.id;
|
||||
}
|
||||
}
|
||||
|
||||
int idx = ui->themeVariant->findData(currentTheme->id);
|
||||
if (idx != -1)
|
||||
if (idx != -1) {
|
||||
ui->themeVariant->setCurrentIndex(idx);
|
||||
}
|
||||
|
||||
ui->themeVariant->setEnabled(ui->themeVariant->count() > 0);
|
||||
ui->themeVariant->blockSignals(false);
|
||||
@@ -89,8 +95,9 @@ void OBSBasicSettings::LoadAppearanceSettings(bool reload)
|
||||
|
||||
if (reload) {
|
||||
QString themeId = ui->theme->currentData().toString();
|
||||
if (ui->themeVariant->currentIndex() != -1)
|
||||
if (ui->themeVariant->currentIndex() != -1) {
|
||||
themeId = ui->themeVariant->currentData().toString();
|
||||
}
|
||||
|
||||
App()->SetTheme(themeId);
|
||||
}
|
||||
|
||||
@@ -114,8 +114,9 @@ void OBSBasicSettings::LoadStream1Settings()
|
||||
protocol = QT_UTF8(obs_service_get_protocol(service_obj));
|
||||
const char *bearer_token = obs_data_get_string(settings, "bearer_token");
|
||||
|
||||
if (is_rtmp_custom || is_whip)
|
||||
if (is_rtmp_custom || is_whip) {
|
||||
ui->customServer->setText(server);
|
||||
}
|
||||
|
||||
if (is_rtmp_custom) {
|
||||
ui->service->setCurrentIndex(0);
|
||||
@@ -131,8 +132,9 @@ void OBSBasicSettings::LoadStream1Settings()
|
||||
} else {
|
||||
int idx = ui->service->findText(service);
|
||||
if (idx == -1) {
|
||||
if (service && *service)
|
||||
if (service && *service) {
|
||||
ui->service->insertItem(1, service);
|
||||
}
|
||||
idx = 1;
|
||||
}
|
||||
ui->service->setCurrentIndex(idx);
|
||||
@@ -156,26 +158,29 @@ void OBSBasicSettings::LoadStream1Settings()
|
||||
|
||||
ui->multitrackVideoMaximumVideoTracksAuto->setChecked(
|
||||
config_get_bool(main->Config(), "Stream1", "MultitrackVideoMaximumVideoTracksAuto"));
|
||||
if (config_has_user_value(main->Config(), "Stream1", "MultitrackVideoMaximumVideoTracks"))
|
||||
if (config_has_user_value(main->Config(), "Stream1", "MultitrackVideoMaximumVideoTracks")) {
|
||||
ui->multitrackVideoMaximumVideoTracks->setValue(
|
||||
config_get_int(main->Config(), "Stream1", "MultitrackVideoMaximumVideoTracks"));
|
||||
}
|
||||
|
||||
ui->multitrackVideoStreamDumpEnable->setChecked(
|
||||
config_get_bool(main->Config(), "Stream1", "MultitrackVideoStreamDumpEnabled"));
|
||||
|
||||
ui->multitrackVideoConfigOverrideEnable->setChecked(
|
||||
config_get_bool(main->Config(), "Stream1", "MultitrackVideoConfigOverrideEnabled"));
|
||||
if (config_has_user_value(main->Config(), "Stream1", "MultitrackVideoConfigOverride"))
|
||||
if (config_has_user_value(main->Config(), "Stream1", "MultitrackVideoConfigOverride")) {
|
||||
ui->multitrackVideoConfigOverride->setPlainText(
|
||||
DeserializeConfigText(
|
||||
config_get_string(main->Config(), "Stream1", "MultitrackVideoConfigOverride"))
|
||||
.c_str());
|
||||
}
|
||||
|
||||
ui->multitrackVideoAdditionalCanvas->clear();
|
||||
ui->multitrackVideoAdditionalCanvas->addItem(QTStr("None"));
|
||||
for (const auto &canvas : main->GetCanvases()) {
|
||||
if (obs_canvas_get_flags(canvas) & EPHEMERAL)
|
||||
if (obs_canvas_get_flags(canvas) & EPHEMERAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ui->multitrackVideoAdditionalCanvas->addItem(obs_canvas_get_name(canvas), obs_canvas_get_uuid(canvas));
|
||||
}
|
||||
@@ -200,15 +205,17 @@ void OBSBasicSettings::LoadStream1Settings()
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
if (server && *server)
|
||||
if (server && *server) {
|
||||
ui->server->insertItem(0, server, server);
|
||||
}
|
||||
idx = 0;
|
||||
}
|
||||
ui->server->setCurrentIndex(idx);
|
||||
}
|
||||
|
||||
if (use_custom_server)
|
||||
if (use_custom_server) {
|
||||
ui->serviceCustomServer->setText(server);
|
||||
}
|
||||
|
||||
if (is_whip) {
|
||||
ui->key->setText(bearer_token);
|
||||
@@ -300,8 +307,9 @@ void OBSBasicSettings::SaveStream1Settings()
|
||||
|
||||
config_set_int(main->Config(), "Twitch", "AddonChoice", newChoice);
|
||||
|
||||
if (choiceExists && currentChoice != newChoice)
|
||||
if (choiceExists && currentChoice != newChoice) {
|
||||
forceAuthReload = true;
|
||||
}
|
||||
|
||||
obs_data_set_bool(settings, "bwtest", ui->bandwidthTestEnable->isChecked());
|
||||
} else {
|
||||
@@ -317,8 +325,9 @@ void OBSBasicSettings::SaveStream1Settings()
|
||||
|
||||
OBSServiceAutoRelease newService = obs_service_create(service_id, "default_service", settings, hotkeyData);
|
||||
|
||||
if (!newService)
|
||||
if (!newService) {
|
||||
return;
|
||||
}
|
||||
|
||||
main->SetService(newService);
|
||||
main->SaveService();
|
||||
@@ -364,8 +373,9 @@ void OBSBasicSettings::SaveStream1Settings()
|
||||
SaveComboData(ui->multitrackVideoAdditionalCanvas, "Stream1", "MultitrackExtraCanvas");
|
||||
|
||||
if (oldMultitrackVideoSetting != ui->enableMultitrackVideo->isChecked() ||
|
||||
oldWHIPSimulcastTotalLayers != ui->whipSimulcastTotalLayers->value())
|
||||
oldWHIPSimulcastTotalLayers != ui->whipSimulcastTotalLayers->value()) {
|
||||
main->ResetOutputs();
|
||||
}
|
||||
|
||||
SwapMultiTrack(QT_TO_UTF8(protocol));
|
||||
}
|
||||
@@ -473,11 +483,13 @@ void OBSBasicSettings::LoadServices(bool showAll)
|
||||
names.push_back(name);
|
||||
}
|
||||
|
||||
if (showAll)
|
||||
if (showAll) {
|
||||
names.sort(Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
for (QString &name : names)
|
||||
for (QString &name : names) {
|
||||
ui->service->addItem(name);
|
||||
}
|
||||
|
||||
if (obs_is_output_protocol_registered("WHIP")) {
|
||||
ui->service->addItem(QTStr("WHIP"), QVariant((int)ListOpt::WHIP));
|
||||
@@ -492,9 +504,10 @@ void OBSBasicSettings::LoadServices(bool showAll)
|
||||
|
||||
if (!lastService.isEmpty()) {
|
||||
int idx = ui->service->findText(lastService);
|
||||
if (idx != -1)
|
||||
if (idx != -1) {
|
||||
ui->service->setCurrentIndex(idx);
|
||||
}
|
||||
}
|
||||
|
||||
ui->service->blockSignals(false);
|
||||
}
|
||||
@@ -584,9 +597,10 @@ void OBSBasicSettings::on_service_currentIndexChanged(int idx)
|
||||
|
||||
if (ServiceSupportsCodecCheck() && UpdateResFPSLimits()) {
|
||||
lastServiceIdx = idx;
|
||||
if (idx == 0)
|
||||
if (idx == 0) {
|
||||
lastCustomServer = ui->customServer->text();
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsCustomService()) {
|
||||
ui->advStreamTrackWidget->setCurrentWidget(ui->streamSingleTracks);
|
||||
@@ -609,8 +623,9 @@ void OBSBasicSettings::on_customServer_textChanged(const QString &)
|
||||
UpdateAdvNetworkGroup();
|
||||
UpdateMultitrackVideo();
|
||||
|
||||
if (ServiceSupportsCodecCheck())
|
||||
if (ServiceSupportsCodecCheck()) {
|
||||
lastCustomServer = ui->customServer->text();
|
||||
}
|
||||
|
||||
SwapMultiTrack(QT_TO_UTF8(protocol));
|
||||
}
|
||||
@@ -672,19 +687,23 @@ void OBSBasicSettings::ServiceChanged(bool resetFields)
|
||||
QString OBSBasicSettings::FindProtocol()
|
||||
{
|
||||
if (IsCustomService()) {
|
||||
if (ui->customServer->text().isEmpty())
|
||||
if (ui->customServer->text().isEmpty()) {
|
||||
return QString("RTMP");
|
||||
}
|
||||
|
||||
QString server = ui->customServer->text();
|
||||
|
||||
if (obs_is_output_protocol_registered("RTMPS") && server.startsWith("rtmps://"))
|
||||
if (obs_is_output_protocol_registered("RTMPS") && server.startsWith("rtmps://")) {
|
||||
return QString("RTMPS");
|
||||
}
|
||||
|
||||
if (server.startsWith("srt://"))
|
||||
if (server.startsWith("srt://")) {
|
||||
return QString("SRT");
|
||||
}
|
||||
|
||||
if (server.startsWith("rist://"))
|
||||
if (server.startsWith("rist://")) {
|
||||
return QString("RIST");
|
||||
}
|
||||
|
||||
} else {
|
||||
OBSProperties props = obs_get_service_properties("rtmp_common");
|
||||
@@ -696,9 +715,10 @@ QString OBSBasicSettings::FindProtocol()
|
||||
obs_property_modified(services, settings);
|
||||
|
||||
const char *protocol = obs_data_get_string(settings, "protocol");
|
||||
if (protocol && *protocol)
|
||||
if (protocol && *protocol) {
|
||||
return QT_UTF8(protocol);
|
||||
}
|
||||
}
|
||||
|
||||
return QString("RTMP");
|
||||
}
|
||||
@@ -776,10 +796,11 @@ OBSService OBSBasicSettings::SpawnTempService()
|
||||
obs_data_set_string(settings, "server", QT_TO_UTF8(ui->customServer->text().trimmed()));
|
||||
}
|
||||
|
||||
if (whip)
|
||||
if (whip) {
|
||||
obs_data_set_string(settings, "bearer_token", QT_TO_UTF8(ui->key->text()));
|
||||
else
|
||||
} else {
|
||||
obs_data_set_string(settings, "key", QT_TO_UTF8(ui->key->text()));
|
||||
}
|
||||
|
||||
OBSServiceAutoRelease newService = obs_service_create(service_id, "temp_service", settings, nullptr);
|
||||
return newService.Get();
|
||||
@@ -792,8 +813,9 @@ void OBSBasicSettings::OnOAuthStreamKeyConnected()
|
||||
if (a) {
|
||||
bool validKey = !a->key().empty();
|
||||
|
||||
if (validKey)
|
||||
if (validKey) {
|
||||
ui->key->setText(QT_UTF8(a->key().c_str()));
|
||||
}
|
||||
|
||||
ui->streamKeyWidget->setVisible(false);
|
||||
ui->streamKeyLabel->setVisible(false);
|
||||
@@ -918,8 +940,9 @@ void OBSBasicSettings::on_useStreamKey_clicked()
|
||||
|
||||
void OBSBasicSettings::on_useAuth_toggled()
|
||||
{
|
||||
if (!IsCustomService())
|
||||
if (!IsCustomService()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool use_auth = ui->useAuth->isChecked();
|
||||
|
||||
@@ -948,11 +971,13 @@ void OBSBasicSettings::UpdateVodTrackSetting()
|
||||
bool enableVodTrack = ui->service->currentText() == "Twitch";
|
||||
bool wasEnabled = !!vodTrackCheckbox;
|
||||
|
||||
if (enableForCustomServer && IsCustomService())
|
||||
if (enableForCustomServer && IsCustomService()) {
|
||||
enableVodTrack = true;
|
||||
}
|
||||
|
||||
if (enableVodTrack == wasEnabled)
|
||||
if (enableVodTrack == wasEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enableVodTrack) {
|
||||
delete vodTrackCheckbox;
|
||||
@@ -1041,16 +1066,19 @@ void OBSBasicSettings::UpdateServiceRecommendations()
|
||||
QString text;
|
||||
|
||||
#define ENFORCE_TEXT(x) QTStr("Basic.Settings.Stream.Recommended." x)
|
||||
if (vbitrate)
|
||||
if (vbitrate) {
|
||||
text += ENFORCE_TEXT("MaxVideoBitrate").arg(QString::number(vbitrate));
|
||||
}
|
||||
if (abitrate) {
|
||||
if (!text.isEmpty())
|
||||
if (!text.isEmpty()) {
|
||||
text += "<br>";
|
||||
}
|
||||
text += ENFORCE_TEXT("MaxAudioBitrate").arg(QString::number(abitrate));
|
||||
}
|
||||
if (res_count) {
|
||||
if (!text.isEmpty())
|
||||
if (!text.isEmpty()) {
|
||||
text += "<br>";
|
||||
}
|
||||
|
||||
obs_service_resolution best_res = {};
|
||||
int best_res_pixels = 0;
|
||||
@@ -1068,8 +1096,9 @@ void OBSBasicSettings::UpdateServiceRecommendations()
|
||||
text += ENFORCE_TEXT("MaxResolution").arg(res_str);
|
||||
}
|
||||
if (fps) {
|
||||
if (!text.isEmpty())
|
||||
if (!text.isEmpty()) {
|
||||
text += "<br>";
|
||||
}
|
||||
|
||||
text += ENFORCE_TEXT("MaxFPS").arg(QString::number(fps));
|
||||
}
|
||||
@@ -1077,8 +1106,9 @@ void OBSBasicSettings::UpdateServiceRecommendations()
|
||||
|
||||
#ifdef YOUTUBE_ENABLED
|
||||
if (IsYouTubeService(QT_TO_UTF8(ui->service->currentText()))) {
|
||||
if (!text.isEmpty())
|
||||
if (!text.isEmpty()) {
|
||||
text += "<br><br>";
|
||||
}
|
||||
|
||||
text += "<a href=\"https://www.youtube.com/t/terms\">"
|
||||
"YouTube Terms of Service</a><br>"
|
||||
@@ -1093,8 +1123,9 @@ void OBSBasicSettings::UpdateServiceRecommendations()
|
||||
|
||||
void OBSBasicSettings::DisplayEnforceWarning(bool checked)
|
||||
{
|
||||
if (IsCustomService())
|
||||
if (IsCustomService()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checked) {
|
||||
SimpleRecordingEncoderChanged();
|
||||
@@ -1119,16 +1150,18 @@ void OBSBasicSettings::DisplayEnforceWarning(bool checked)
|
||||
|
||||
bool OBSBasicSettings::ResFPSValid(obs_service_resolution *res_list, size_t res_count, int max_fps)
|
||||
{
|
||||
if (!res_count && !max_fps)
|
||||
if (!res_count && !max_fps) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (res_count) {
|
||||
QString res = ui->outputResolution->currentText();
|
||||
bool found_res = false;
|
||||
|
||||
int cx, cy;
|
||||
if (sscanf(QT_TO_UTF8(res), "%dx%d", &cx, &cy) != 2)
|
||||
if (sscanf(QT_TO_UTF8(res), "%dx%d", &cx, &cy) != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < res_count; i++) {
|
||||
if (res_list[i].cx == cx && res_list[i].cy == cy) {
|
||||
@@ -1137,21 +1170,24 @@ bool OBSBasicSettings::ResFPSValid(obs_service_resolution *res_list, size_t res_
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_res)
|
||||
if (!found_res) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_fps) {
|
||||
int fpsType = ui->fpsType->currentIndex();
|
||||
if (fpsType != 0)
|
||||
if (fpsType != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string fps_str = ui->fpsCommon->currentText().toStdString();
|
||||
float fps;
|
||||
sscanf(fps_str.c_str(), "%f", &fps);
|
||||
if (fps > (float)max_fps)
|
||||
if (fps > (float)max_fps) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1177,12 +1213,14 @@ extern void set_closest_res(int &cx, int &cy, struct obs_service_resolution *res
|
||||
*/
|
||||
bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
{
|
||||
if (loading)
|
||||
if (loading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = ui->service->currentIndex();
|
||||
if (idx == -1)
|
||||
if (idx == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ignoreRecommended = ui->ignoreRecommended->isChecked();
|
||||
BPtr<obs_service_resolution> res_list;
|
||||
@@ -1207,8 +1245,9 @@ bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
|
||||
sscanf(QT_TO_UTF8(res), "%dx%d", &cx, &cy);
|
||||
|
||||
if (res_count)
|
||||
if (res_count) {
|
||||
set_closest_res(cx, cy, res_list, res_count);
|
||||
}
|
||||
|
||||
if (max_fps) {
|
||||
int fpsType = ui->fpsType->currentIndex();
|
||||
@@ -1263,11 +1302,13 @@ bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
#define WARNING_VAL(x) QTStr("Basic.Settings.Output.Warn.EnforceResolutionFPS." x)
|
||||
|
||||
QString str;
|
||||
if (res_count)
|
||||
if (res_count) {
|
||||
str += WARNING_VAL("Resolution").arg(res_str);
|
||||
}
|
||||
if (max_fps) {
|
||||
if (!str.isEmpty())
|
||||
if (!str.isEmpty()) {
|
||||
str += "\n";
|
||||
}
|
||||
str += WARNING_VAL("FPS").arg(fps_str);
|
||||
}
|
||||
|
||||
@@ -1275,12 +1316,13 @@ bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
#undef WARNING_VAL
|
||||
|
||||
if (button == QMessageBox::No) {
|
||||
if (idx != lastServiceIdx)
|
||||
if (idx != lastServiceIdx) {
|
||||
QMetaObject::invokeMethod(ui->service, "setCurrentIndex", Qt::QueuedConnection,
|
||||
Q_ARG(int, lastServiceIdx));
|
||||
else
|
||||
} else {
|
||||
QMetaObject::invokeMethod(ui->ignoreRecommended, "setChecked", Qt::QueuedConnection,
|
||||
Q_ARG(bool, true));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1303,9 +1345,10 @@ bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
QString str = QString("%1x%2").arg(QString::number(val.cx), QString::number(val.cy));
|
||||
ui->outputResolution->addItem(str);
|
||||
|
||||
if (val.cx == cx && val.cy == cy)
|
||||
if (val.cx == cx && val.cy == cy) {
|
||||
new_res_index = (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
ui->outputResolution->setCurrentIndex(new_res_index);
|
||||
if (!valid) {
|
||||
@@ -1347,9 +1390,10 @@ bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
EnableApplyButton(true);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < ui->fpsCommon->count(); i++)
|
||||
for (int i = 0; i < ui->fpsCommon->count(); i++) {
|
||||
SetComboItemEnabled(ui->fpsCommon, i, true);
|
||||
}
|
||||
}
|
||||
|
||||
SetComboItemEnabled(ui->fpsType, 1, !max_fps);
|
||||
SetComboItemEnabled(ui->fpsType, 2, !max_fps);
|
||||
@@ -1363,12 +1407,14 @@ bool OBSBasicSettings::UpdateResFPSLimits()
|
||||
|
||||
static bool service_supports_codec(const char **codecs, const char *codec)
|
||||
{
|
||||
if (!codecs)
|
||||
if (!codecs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
while (*codecs) {
|
||||
if (strcmp(*codecs, codec) == 0)
|
||||
if (strcmp(*codecs, codec) == 0) {
|
||||
return true;
|
||||
}
|
||||
codecs++;
|
||||
}
|
||||
|
||||
@@ -1380,8 +1426,9 @@ extern const char *get_simple_output_encoder(const char *name);
|
||||
|
||||
static inline bool service_supports_encoder(const char **codecs, const char *encoder)
|
||||
{
|
||||
if (!EncoderAvailable(encoder))
|
||||
if (!EncoderAvailable(encoder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *codec = obs_get_encoder_codec(encoder);
|
||||
return service_supports_codec(codecs, codec);
|
||||
@@ -1470,14 +1517,18 @@ bool OBSBasicSettings::ServiceAndACodecCompatible()
|
||||
static QString get_adv_fallback(const QString &enc)
|
||||
{
|
||||
if (enc == "obs_nvenc_hevc_tex" || enc == "obs_nvenc_av1_tex" || enc == "jim_hevc_nvenc" ||
|
||||
enc == "jim_av1_nvenc")
|
||||
enc == "jim_av1_nvenc") {
|
||||
return "obs_nvenc_h264_tex";
|
||||
if (enc == "h265_texture_amf" || enc == "av1_texture_amf")
|
||||
}
|
||||
if (enc == "h265_texture_amf" || enc == "av1_texture_amf") {
|
||||
return "h264_texture_amf";
|
||||
if (enc == "com.apple.videotoolbox.videoencoder.ave.hevc")
|
||||
}
|
||||
if (enc == "com.apple.videotoolbox.videoencoder.ave.hevc") {
|
||||
return "com.apple.videotoolbox.videoencoder.ave.avc";
|
||||
if (enc == "obs_qsv11_av1")
|
||||
}
|
||||
if (enc == "obs_qsv11_av1") {
|
||||
return "obs_qsv11";
|
||||
}
|
||||
return "obs_x264";
|
||||
}
|
||||
|
||||
@@ -1485,42 +1536,50 @@ static QString get_adv_audio_fallback(const QString &enc)
|
||||
{
|
||||
const char *codec = obs_get_encoder_codec(QT_TO_UTF8(enc));
|
||||
|
||||
if (codec && strcmp(codec, "aac") == 0)
|
||||
if (codec && strcmp(codec, "aac") == 0) {
|
||||
return "ffmpeg_opus";
|
||||
}
|
||||
|
||||
QString aac_default = "ffmpeg_aac";
|
||||
if (EncoderAvailable("CoreAudio_AAC"))
|
||||
if (EncoderAvailable("CoreAudio_AAC")) {
|
||||
aac_default = "CoreAudio_AAC";
|
||||
else if (EncoderAvailable("libfdk_aac"))
|
||||
} else if (EncoderAvailable("libfdk_aac")) {
|
||||
aac_default = "libfdk_aac";
|
||||
}
|
||||
|
||||
return aac_default;
|
||||
}
|
||||
|
||||
static QString get_simple_fallback(const QString &enc)
|
||||
{
|
||||
if (enc == SIMPLE_ENCODER_NVENC_HEVC || enc == SIMPLE_ENCODER_NVENC_AV1)
|
||||
if (enc == SIMPLE_ENCODER_NVENC_HEVC || enc == SIMPLE_ENCODER_NVENC_AV1) {
|
||||
return SIMPLE_ENCODER_NVENC;
|
||||
if (enc == SIMPLE_ENCODER_AMD_HEVC || enc == SIMPLE_ENCODER_AMD_AV1)
|
||||
}
|
||||
if (enc == SIMPLE_ENCODER_AMD_HEVC || enc == SIMPLE_ENCODER_AMD_AV1) {
|
||||
return SIMPLE_ENCODER_AMD;
|
||||
if (enc == SIMPLE_ENCODER_APPLE_HEVC)
|
||||
}
|
||||
if (enc == SIMPLE_ENCODER_APPLE_HEVC) {
|
||||
return SIMPLE_ENCODER_APPLE_H264;
|
||||
if (enc == SIMPLE_ENCODER_QSV_AV1)
|
||||
}
|
||||
if (enc == SIMPLE_ENCODER_QSV_AV1) {
|
||||
return SIMPLE_ENCODER_QSV;
|
||||
}
|
||||
return SIMPLE_ENCODER_X264;
|
||||
}
|
||||
|
||||
bool OBSBasicSettings::ServiceSupportsCodecCheck()
|
||||
{
|
||||
if (loading)
|
||||
if (loading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vcodec_compat = ServiceAndVCodecCompatible();
|
||||
bool acodec_compat = ServiceAndACodecCompatible();
|
||||
|
||||
if (vcodec_compat && acodec_compat) {
|
||||
if (lastServiceIdx != ui->service->currentIndex() || IsCustomService())
|
||||
if (lastServiceIdx != ui->service->currentIndex() || IsCustomService()) {
|
||||
ResetEncoders(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1568,19 +1627,21 @@ bool OBSBasicSettings::ServiceSupportsCodecCheck()
|
||||
|
||||
QString msg = WARNING_VAL("Msg").arg(service, vcodec_compat ? cur_audio_name : cur_video_name,
|
||||
vcodec_compat ? fb_audio_name : fb_video_name);
|
||||
if (!vcodec_compat && !acodec_compat)
|
||||
if (!vcodec_compat && !acodec_compat) {
|
||||
msg = WARNING_VAL("Msg2").arg(service, cur_video_name, cur_audio_name, fb_video_name, fb_audio_name);
|
||||
}
|
||||
|
||||
auto button = OBSMessageBox::question(this, WARNING_VAL("Title"), msg);
|
||||
#undef WARNING_VAL
|
||||
|
||||
if (button == QMessageBox::No) {
|
||||
if (lastServiceIdx == 0 && lastServiceIdx == ui->service->currentIndex())
|
||||
if (lastServiceIdx == 0 && lastServiceIdx == ui->service->currentIndex()) {
|
||||
QMetaObject::invokeMethod(ui->customServer, "setText", Qt::QueuedConnection,
|
||||
Q_ARG(QString, lastCustomServer));
|
||||
else
|
||||
} else {
|
||||
QMetaObject::invokeMethod(ui->service, "setCurrentIndex", Qt::QueuedConnection,
|
||||
Q_ARG(int, lastServiceIdx));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1650,22 +1711,27 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
|
||||
QString qType = QT_UTF8(type);
|
||||
|
||||
if (obs_get_encoder_type(type) == OBS_ENCODER_VIDEO) {
|
||||
if ((caps & ENCODER_HIDE_FLAGS) != 0)
|
||||
if ((caps & ENCODER_HIDE_FLAGS) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (service_supports_codec(vcodecs, codec))
|
||||
if (service_supports_codec(vcodecs, codec)) {
|
||||
ui->advOutEncoder->addItem(qName, qType);
|
||||
if (!streamOnly)
|
||||
}
|
||||
if (!streamOnly) {
|
||||
ui->advOutRecEncoder->addItem(qName, qType);
|
||||
}
|
||||
}
|
||||
|
||||
if (obs_get_encoder_type(type) == OBS_ENCODER_AUDIO) {
|
||||
if (service_supports_codec(acodecs, codec))
|
||||
if (service_supports_codec(acodecs, codec)) {
|
||||
ui->advOutAEncoder->addItem(qName, qType);
|
||||
if (!streamOnly)
|
||||
}
|
||||
if (!streamOnly) {
|
||||
ui->advOutRecAEncoder->addItem(qName, qType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->advOutEncoder->model()->sort(0);
|
||||
ui->advOutAEncoder->model()->sort(0);
|
||||
@@ -1684,26 +1750,34 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
|
||||
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Software"), QString(SIMPLE_ENCODER_X264));
|
||||
#ifdef _WIN32
|
||||
if (service_supports_encoder(vcodecs, "obs_qsv11"))
|
||||
if (service_supports_encoder(vcodecs, "obs_qsv11")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.QSV.H264"), QString(SIMPLE_ENCODER_QSV));
|
||||
if (service_supports_encoder(vcodecs, "obs_qsv11_av1"))
|
||||
}
|
||||
if (service_supports_encoder(vcodecs, "obs_qsv11_av1")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.QSV.AV1"), QString(SIMPLE_ENCODER_QSV_AV1));
|
||||
}
|
||||
#endif
|
||||
if (service_supports_encoder(vcodecs, "ffmpeg_nvenc"))
|
||||
if (service_supports_encoder(vcodecs, "ffmpeg_nvenc")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.NVENC.H264"), QString(SIMPLE_ENCODER_NVENC));
|
||||
if (service_supports_encoder(vcodecs, "obs_nvenc_av1_tex"))
|
||||
}
|
||||
if (service_supports_encoder(vcodecs, "obs_nvenc_av1_tex")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.NVENC.AV1"), QString(SIMPLE_ENCODER_NVENC_AV1));
|
||||
}
|
||||
#ifdef ENABLE_HEVC
|
||||
if (service_supports_encoder(vcodecs, "h265_texture_amf"))
|
||||
if (service_supports_encoder(vcodecs, "h265_texture_amf")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.AMD.HEVC"), QString(SIMPLE_ENCODER_AMD_HEVC));
|
||||
if (service_supports_encoder(vcodecs, "ffmpeg_hevc_nvenc"))
|
||||
}
|
||||
if (service_supports_encoder(vcodecs, "ffmpeg_hevc_nvenc")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.NVENC.HEVC"),
|
||||
QString(SIMPLE_ENCODER_NVENC_HEVC));
|
||||
}
|
||||
#endif
|
||||
if (service_supports_encoder(vcodecs, "h264_texture_amf"))
|
||||
if (service_supports_encoder(vcodecs, "h264_texture_amf")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.AMD.H264"), QString(SIMPLE_ENCODER_AMD));
|
||||
if (service_supports_encoder(vcodecs, "av1_texture_amf"))
|
||||
}
|
||||
if (service_supports_encoder(vcodecs, "av1_texture_amf")) {
|
||||
ui->simpleOutStrEncoder->addItem(ENCODER_STR("Hardware.AMD.AV1"), QString(SIMPLE_ENCODER_AMD_AV1));
|
||||
}
|
||||
/* Preprocessor guard required for the macOS version check */
|
||||
#ifdef __APPLE__
|
||||
if (service_supports_encoder(vcodecs, "com.apple.videotoolbox.videoencoder.ave.avc")
|
||||
@@ -1730,10 +1804,12 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly)
|
||||
#endif
|
||||
#endif
|
||||
if (service_supports_encoder(acodecs, "CoreAudio_AAC") || service_supports_encoder(acodecs, "libfdk_aac") ||
|
||||
service_supports_encoder(acodecs, "ffmpeg_aac"))
|
||||
service_supports_encoder(acodecs, "ffmpeg_aac")) {
|
||||
ui->simpleOutStrAEncoder->addItem(QTStr("Basic.Settings.Output.Simple.Codec.AAC.Default"), "aac");
|
||||
if (service_supports_encoder(acodecs, "ffmpeg_opus"))
|
||||
}
|
||||
if (service_supports_encoder(acodecs, "ffmpeg_opus")) {
|
||||
ui->simpleOutStrAEncoder->addItem(QTStr("Basic.Settings.Output.Simple.Codec.Opus"), "opus");
|
||||
}
|
||||
#undef ENCODER_STR
|
||||
|
||||
/* ------------------------------------------------- */
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
|
||||
void OBSHotkeyEdit::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->isAutoRepeat())
|
||||
if (event->isAutoRepeat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_key_combination_t new_key;
|
||||
|
||||
@@ -70,11 +71,13 @@ QVariant OBSHotkeyEdit::inputMethodQuery(Qt::InputMethodQuery query) const
|
||||
#ifdef __APPLE__
|
||||
void OBSHotkeyEdit::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->isAutoRepeat())
|
||||
if (event->isAutoRepeat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->key() != Qt::Key_CapsLock)
|
||||
if (event->key() != Qt::Key_CapsLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_key_combination_t new_key;
|
||||
|
||||
@@ -140,8 +143,9 @@ void OBSHotkeyEdit::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
void OBSHotkeyEdit::HandleNewKey(obs_key_combination_t new_key)
|
||||
{
|
||||
if (new_key == key || obs_key_combination_is_empty(new_key))
|
||||
if (new_key == key || obs_key_combination_is_empty(new_key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
key = new_key;
|
||||
|
||||
@@ -181,11 +185,13 @@ void OBSHotkeyEdit::ClearKey()
|
||||
|
||||
void OBSHotkeyEdit::UpdateDuplicationState()
|
||||
{
|
||||
if (!dupeIcon && !hasDuplicate)
|
||||
if (!dupeIcon && !hasDuplicate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dupeIcon)
|
||||
if (!dupeIcon) {
|
||||
CreateDupeIcon();
|
||||
}
|
||||
|
||||
if (dupeIcon->isVisible() != hasDuplicate) {
|
||||
dupeIcon->setVisible(hasDuplicate);
|
||||
|
||||
@@ -33,8 +33,9 @@ static inline void updateStyle(QWidget *widget)
|
||||
|
||||
void OBSHotkeyLabel::highlightPair(bool highlight)
|
||||
{
|
||||
if (!pairPartner)
|
||||
if (!pairPartner) {
|
||||
return;
|
||||
}
|
||||
|
||||
pairPartner->setProperty("class", highlight ? "text-bright" : "");
|
||||
updateStyle(pairPartner);
|
||||
@@ -45,8 +46,9 @@ void OBSHotkeyLabel::highlightPair(bool highlight)
|
||||
void OBSHotkeyLabel::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
|
||||
if (!pairPartner)
|
||||
if (!pairPartner) {
|
||||
return;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
highlightPair(true);
|
||||
@@ -54,8 +56,9 @@ void OBSHotkeyLabel::enterEvent(QEnterEvent *event)
|
||||
|
||||
void OBSHotkeyLabel::leaveEvent(QEvent *event)
|
||||
{
|
||||
if (!pairPartner)
|
||||
if (!pairPartner) {
|
||||
return;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
highlightPair(false);
|
||||
@@ -64,6 +67,7 @@ void OBSHotkeyLabel::leaveEvent(QEvent *event)
|
||||
void OBSHotkeyLabel::setToolTip(const QString &toolTip)
|
||||
{
|
||||
QLabel::setToolTip(toolTip);
|
||||
if (widget)
|
||||
if (widget) {
|
||||
widget->setToolTip(toolTip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,14 @@
|
||||
|
||||
void OBSHotkeyWidget::SetKeyCombinations(const std::vector<obs_key_combination_t> &combos)
|
||||
{
|
||||
if (combos.empty())
|
||||
if (combos.empty()) {
|
||||
AddEdit({0, OBS_KEY_NONE});
|
||||
}
|
||||
|
||||
for (auto combo : combos)
|
||||
for (auto combo : combos) {
|
||||
AddEdit(combo);
|
||||
}
|
||||
}
|
||||
|
||||
bool OBSHotkeyWidget::Changed() const
|
||||
{
|
||||
@@ -47,17 +49,20 @@ void OBSHotkeyWidget::Apply()
|
||||
|
||||
changed = false;
|
||||
|
||||
for (auto &revertButton : revertButtons)
|
||||
for (auto &revertButton : revertButtons) {
|
||||
revertButton->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::GetCombinations(std::vector<obs_key_combination_t> &combinations) const
|
||||
{
|
||||
combinations.clear();
|
||||
for (auto &edit : edits)
|
||||
if (!obs_key_combination_is_empty(edit->key))
|
||||
for (auto &edit : edits) {
|
||||
if (!obs_key_combination_is_empty(edit->key)) {
|
||||
combinations.emplace_back(edit->key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::Save()
|
||||
{
|
||||
@@ -130,8 +135,9 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
||||
subLayout->addWidget(add);
|
||||
subLayout->addWidget(remove);
|
||||
|
||||
if (removeButtons.size() == 1)
|
||||
if (removeButtons.size() == 1) {
|
||||
removeButtons.front()->setEnabled(true);
|
||||
}
|
||||
|
||||
if (idx != -1) {
|
||||
revertButtons.insert(begin(revertButtons) + idx, revert);
|
||||
@@ -172,8 +178,9 @@ void OBSHotkeyWidget::RemoveEdit(size_t idx, bool signal)
|
||||
}
|
||||
delete item;
|
||||
|
||||
if (removeButtons.size() == 1)
|
||||
if (removeButtons.size() == 1) {
|
||||
removeButtons.front()->setEnabled(false);
|
||||
}
|
||||
|
||||
emit KeyChanged();
|
||||
}
|
||||
@@ -188,13 +195,15 @@ void OBSHotkeyWidget::BindingsChanged(void *data, calldata_t *param)
|
||||
|
||||
void OBSHotkeyWidget::HandleChangedBindings(obs_hotkey_id id_)
|
||||
{
|
||||
if (ignoreChangedBindings || id != id_)
|
||||
if (ignoreChangedBindings || id != id_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<obs_key_combination_t> bindings;
|
||||
auto LoadBindings = [&](obs_hotkey_binding_t *binding) {
|
||||
if (obs_hotkey_binding_get_hotkey_id(binding) != id)
|
||||
if (obs_hotkey_binding_get_hotkey_id(binding) != id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto get_combo = obs_hotkey_binding_get_key_combination;
|
||||
bindings.push_back(get_combo(binding));
|
||||
@@ -209,16 +218,18 @@ void OBSHotkeyWidget::HandleChangedBindings(obs_hotkey_id id_)
|
||||
},
|
||||
static_cast<void *>(&LoadBindings));
|
||||
|
||||
while (edits.size() > 0)
|
||||
while (edits.size() > 0) {
|
||||
RemoveEdit(edits.size() - 1, false);
|
||||
}
|
||||
|
||||
SetKeyCombinations(bindings);
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::enterEvent(QEnterEvent *event)
|
||||
{
|
||||
if (!label)
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
label->highlightPair(true);
|
||||
@@ -226,8 +237,9 @@ void OBSHotkeyWidget::enterEvent(QEnterEvent *event)
|
||||
|
||||
void OBSHotkeyWidget::leaveEvent(QEvent *event)
|
||||
{
|
||||
if (!label)
|
||||
if (!label) {
|
||||
return;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
label->highlightPair(false);
|
||||
|
||||
@@ -63,9 +63,10 @@ public:
|
||||
void setToolTip(const QString &toolTip_)
|
||||
{
|
||||
toolTip = toolTip_;
|
||||
for (auto &edit : edits)
|
||||
for (auto &edit : edits) {
|
||||
edit->setToolTip(toolTip_);
|
||||
}
|
||||
}
|
||||
|
||||
void Apply();
|
||||
void GetCombinations(std::vector<obs_key_combination_t> &) const;
|
||||
|
||||
+16
-10
@@ -47,29 +47,35 @@ bool CalculateFileHash(const wchar_t *path, B2Hash &hash)
|
||||
{
|
||||
static __declspec(thread) vector<BYTE> hashBuffer;
|
||||
blake2b_state blake2;
|
||||
if (blake2b_init(&blake2, kBlake2HashLength) != 0)
|
||||
if (blake2b_init(&blake2, kBlake2HashLength) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hashBuffer.resize(1048576);
|
||||
|
||||
WinHandle handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
DWORD read = 0;
|
||||
if (!ReadFile(handle, hashBuffer.data(), (DWORD)hashBuffer.size(), &read, nullptr))
|
||||
return false;
|
||||
|
||||
if (!read)
|
||||
break;
|
||||
|
||||
if (blake2b_update(&blake2, hashBuffer.data(), read) != 0)
|
||||
if (!ReadFile(handle, hashBuffer.data(), (DWORD)hashBuffer.size(), &read, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blake2b_final(&blake2, hash.data(), hash.size()) != 0)
|
||||
if (!read) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (blake2b_update(&blake2, hashBuffer.data(), read) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (blake2b_final(&blake2, hash.data(), hash.size()) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@ public:
|
||||
inline CustomHandle(T in) : handle(in) {}
|
||||
inline ~CustomHandle()
|
||||
{
|
||||
if (handle)
|
||||
if (handle) {
|
||||
freefunc(handle);
|
||||
}
|
||||
}
|
||||
|
||||
inline T *operator&() { return &handle; }
|
||||
inline operator T() const { return handle; }
|
||||
@@ -24,8 +25,9 @@ public:
|
||||
|
||||
inline CustomHandle<T, freefunc> &operator=(T in)
|
||||
{
|
||||
if (handle)
|
||||
if (handle) {
|
||||
freefunc(handle);
|
||||
}
|
||||
handle = in;
|
||||
return *this;
|
||||
}
|
||||
|
||||
+20
-10
@@ -67,8 +67,9 @@ bool HTTPPostData(const wchar_t *url, const BYTE *data, int dataLen, const wchar
|
||||
|
||||
WinHttpCrackUrl(url, 0, 0, &urlComponents);
|
||||
|
||||
if (urlComponents.nPort == 443)
|
||||
if (urlComponents.nPort == 443) {
|
||||
secure = true;
|
||||
}
|
||||
|
||||
/* -------------------------------------- *
|
||||
* connect to server */
|
||||
@@ -146,8 +147,9 @@ bool HTTPPostData(const wchar_t *url, const BYTE *data, int dataLen, const wchar
|
||||
*responseCode = wcstoul(statusCode, nullptr, 10);
|
||||
|
||||
/* are we supposed to return true here? */
|
||||
if (!bResults || *responseCode != 200)
|
||||
if (!bResults || *responseCode != 200) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BYTE buffer[READ_BUF_SIZE];
|
||||
DWORD dwSize, outSize;
|
||||
@@ -167,8 +169,9 @@ bool HTTPPostData(const wchar_t *url, const BYTE *data, int dataLen, const wchar
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!outSize)
|
||||
if (!outSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ReadHTTPData(responseBuf, buffer, outSize)) {
|
||||
*responseCode = -6;
|
||||
@@ -240,8 +243,9 @@ bool HTTPGetFile(HINTERNET hConnect, const wchar_t *url, const wchar_t *outputPa
|
||||
|
||||
WinHttpCrackUrl(url, 0, 0, &urlComponents);
|
||||
|
||||
if (urlComponents.nPort == 443)
|
||||
if (urlComponents.nPort == 443) {
|
||||
secure = true;
|
||||
}
|
||||
|
||||
/* -------------------------------------- *
|
||||
* request data */
|
||||
@@ -287,8 +291,9 @@ bool HTTPGetFile(HINTERNET hConnect, const wchar_t *url, const wchar_t *outputPa
|
||||
*responseCode = wcstoul(statusCode, nullptr, 10);
|
||||
|
||||
/* are we supposed to return true here? */
|
||||
if (!bResults || *responseCode != 200)
|
||||
if (!bResults || *responseCode != 200) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BYTE buffer[READ_BUF_SIZE];
|
||||
DWORD dwSize, outSize;
|
||||
@@ -313,11 +318,13 @@ bool HTTPGetFile(HINTERNET hConnect, const wchar_t *url, const wchar_t *outputPa
|
||||
*responseCode = -9;
|
||||
return false;
|
||||
} else {
|
||||
if (!outSize)
|
||||
if (!outSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ReadHTTPFile(updateFile, buffer, outSize, responseCode))
|
||||
if (!ReadHTTPFile(updateFile, buffer, outSize, responseCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateProgressBar();
|
||||
}
|
||||
@@ -358,8 +365,9 @@ bool HTTPGetBuffer(HINTERNET hConnect, const wchar_t *url, const wchar_t *extraH
|
||||
|
||||
WinHttpCrackUrl(url, 0, 0, &urlComponents);
|
||||
|
||||
if (urlComponents.nPort == 443)
|
||||
if (urlComponents.nPort == 443) {
|
||||
secure = true;
|
||||
}
|
||||
|
||||
/* -------------------------------------- *
|
||||
* request data */
|
||||
@@ -405,8 +413,9 @@ bool HTTPGetBuffer(HINTERNET hConnect, const wchar_t *url, const wchar_t *extraH
|
||||
*responseCode = wcstoul(statusCode, nullptr, 10);
|
||||
|
||||
/* are we supposed to return true here? */
|
||||
if (!bResults || *responseCode != 200)
|
||||
if (!bResults || *responseCode != 200) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BYTE buffer[READ_BUF_SIZE];
|
||||
DWORD dwSize, outSize;
|
||||
@@ -425,8 +434,9 @@ bool HTTPGetBuffer(HINTERNET hConnect, const wchar_t *url, const wchar_t *extraH
|
||||
*responseCode = -9;
|
||||
return false;
|
||||
} else {
|
||||
if (!outSize)
|
||||
if (!outSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
out.insert(out.end(), (std::byte *)buffer, (std::byte *)buffer + outSize);
|
||||
|
||||
|
||||
+20
-10
@@ -42,8 +42,9 @@ static int64_t offtin(const uint8_t *buf)
|
||||
y = y * 256;
|
||||
y += buf[0];
|
||||
|
||||
if (buf[7] & 0x80)
|
||||
if (buf[7] & 0x80) {
|
||||
y = -y;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
@@ -65,21 +66,24 @@ try {
|
||||
* open patch and file to patch */
|
||||
|
||||
hTarget = CreateFile(targetFile, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (!hTarget.Valid())
|
||||
if (!hTarget.Valid()) {
|
||||
throw int(GetLastError());
|
||||
}
|
||||
|
||||
/* --------------------------------- *
|
||||
* read patch header */
|
||||
|
||||
if (memcmp(patch_data, kDeltaMagic, kMagicSize) != 0)
|
||||
if (memcmp(patch_data, kDeltaMagic, kMagicSize) != 0) {
|
||||
throw int(-4);
|
||||
}
|
||||
|
||||
/* --------------------------------- *
|
||||
* allocate new file size data */
|
||||
|
||||
newsize = offtin((const uint8_t *)patch_data + kMagicSize);
|
||||
if (newsize < 0 || newsize >= 0x7ffffffff)
|
||||
if (newsize < 0 || newsize >= 0x7ffffffff) {
|
||||
throw int(-5);
|
||||
}
|
||||
|
||||
vector<std::byte> newData;
|
||||
try {
|
||||
@@ -95,8 +99,9 @@ try {
|
||||
DWORD oldFileSize;
|
||||
|
||||
oldFileSize = GetFileSize(hTarget, nullptr);
|
||||
if (oldFileSize == INVALID_FILE_SIZE)
|
||||
if (oldFileSize == INVALID_FILE_SIZE) {
|
||||
throw int(GetLastError());
|
||||
}
|
||||
|
||||
vector<std::byte> oldData;
|
||||
try {
|
||||
@@ -105,10 +110,12 @@ try {
|
||||
throw int(-1);
|
||||
}
|
||||
|
||||
if (!ReadFile(hTarget, oldData.data(), oldFileSize, &read, nullptr))
|
||||
if (!ReadFile(hTarget, oldData.data(), oldFileSize, &read, nullptr)) {
|
||||
throw int(GetLastError());
|
||||
if (read != oldFileSize)
|
||||
}
|
||||
if (read != oldFileSize) {
|
||||
throw int(-1);
|
||||
}
|
||||
|
||||
/* --------------------------------- *
|
||||
* patch to new file data */
|
||||
@@ -116,22 +123,25 @@ try {
|
||||
size_t result = ZSTD_decompress_usingDict(zstdCtx, newData.data(), newData.size(), patch_data + kHeaderSize,
|
||||
patch_size - kHeaderSize, oldData.data(), oldData.size());
|
||||
|
||||
if (result != newsize || ZSTD_isError(result))
|
||||
if (result != newsize || ZSTD_isError(result)) {
|
||||
throw int(-9);
|
||||
}
|
||||
|
||||
/* --------------------------------- *
|
||||
* write new file */
|
||||
|
||||
hTarget = nullptr;
|
||||
hTarget = CreateFile(targetFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr);
|
||||
if (!hTarget.Valid())
|
||||
if (!hTarget.Valid()) {
|
||||
throw int(GetLastError());
|
||||
}
|
||||
|
||||
DWORD written;
|
||||
|
||||
success = !!WriteFile(hTarget, newData.data(), (DWORD)newsize, &written, nullptr);
|
||||
if (!success || written != newsize)
|
||||
if (!success || written != newsize) {
|
||||
throw int(GetLastError());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
+171
-87
@@ -91,16 +91,19 @@ static bool IsVSRedistOutdated()
|
||||
const wchar_t vc_dll[] = L"msvcp140";
|
||||
|
||||
auto size = GetFileVersionInfoSize(vc_dll, nullptr);
|
||||
if (!size)
|
||||
if (!size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
buf.resize(size);
|
||||
if (!GetFileVersionInfo(vc_dll, 0, size, buf.data()))
|
||||
if (!GetFileVersionInfo(vc_dll, 0, size, buf.data())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool success = VerQueryValue(buf.data(), L"\\", reinterpret_cast<LPVOID *>(&info), &len);
|
||||
if (!success || !info || !len)
|
||||
if (!success || !info || !len) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return LOWORD(info->dwFileVersionMS) < 40;
|
||||
}
|
||||
@@ -114,8 +117,9 @@ static void Log(const wchar_t *fmt, ...)
|
||||
int len = _vscwprintf(fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (len <= 0)
|
||||
if (len <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Using len + 1 for null terminator, which gets chopped off below */
|
||||
wstring str(len + 1, L'\0');
|
||||
@@ -124,8 +128,9 @@ static void Log(const wchar_t *fmt, ...)
|
||||
len = _vsnwprintf_s(str.data(), len + 1, _TRUNCATE, fmt, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (len <= 0)
|
||||
if (len <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Append newline and send to main window as a PostMessage to
|
||||
* avoid blocking worker threads with UI messages */
|
||||
@@ -159,29 +164,35 @@ try {
|
||||
|
||||
hSrc = CreateFile(src, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
nullptr);
|
||||
if (!hSrc.Valid())
|
||||
if (!hSrc.Valid()) {
|
||||
throw LastError();
|
||||
}
|
||||
|
||||
hDest = CreateFile(dest, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr);
|
||||
if (!hDest.Valid())
|
||||
if (!hDest.Valid()) {
|
||||
throw LastError();
|
||||
}
|
||||
|
||||
BYTE buf[65536];
|
||||
DWORD read, wrote;
|
||||
|
||||
for (;;) {
|
||||
if (!ReadFile(hSrc, buf, sizeof(buf), &read, nullptr))
|
||||
if (!ReadFile(hSrc, buf, sizeof(buf), &read, nullptr)) {
|
||||
throw LastError();
|
||||
}
|
||||
|
||||
if (read == 0)
|
||||
if (read == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WriteFile(hDest, buf, read, &wrote, nullptr))
|
||||
if (!WriteFile(hDest, buf, read, &wrote, nullptr)) {
|
||||
throw LastError();
|
||||
}
|
||||
|
||||
if (wrote != read)
|
||||
if (wrote != read) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -193,12 +204,14 @@ try {
|
||||
static void MyDeleteFile(const wstring &filename)
|
||||
{
|
||||
/* Try straightforward delete first */
|
||||
if (DeleteFile(filename.c_str()))
|
||||
if (DeleteFile(filename.c_str())) {
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD err = GetLastError();
|
||||
if (err == ERROR_FILE_NOT_FOUND)
|
||||
if (err == ERROR_FILE_NOT_FOUND) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If all else fails, schedule the file to be deleted on reboot */
|
||||
MoveFileEx(filename.c_str(), nullptr, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||||
@@ -208,18 +221,22 @@ static bool IsSafeFilename(const wchar_t *path)
|
||||
{
|
||||
const wchar_t *p = path;
|
||||
|
||||
if (!*p)
|
||||
if (!*p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wcsstr(path, L".."))
|
||||
if (wcsstr(path, L"..")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*p == '/')
|
||||
if (*p == '/') {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (*p) {
|
||||
if (!isalnum(*p) && *p != '.' && *p != '/' && *p != '_' && *p != '-')
|
||||
if (!isalnum(*p) && *p != '.' && *p != '/' && *p != '_' && *p != '-') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
@@ -258,12 +275,14 @@ static bool QuickWriteFile(const wchar_t *file, const void *data, size_t size)
|
||||
try {
|
||||
WinHandle handle = CreateFile(file, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
throw LastError();
|
||||
}
|
||||
|
||||
DWORD written;
|
||||
if (!WriteFile(handle, data, (DWORD)size, &written, nullptr))
|
||||
if (!WriteFile(handle, data, (DWORD)size, &written, nullptr)) {
|
||||
throw LastError();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -351,9 +370,10 @@ struct deletion_t {
|
||||
|
||||
void UndoRename() const
|
||||
{
|
||||
if (!deleteMeFilename.empty())
|
||||
if (!deleteMeFilename.empty()) {
|
||||
MoveFile(deleteMeFilename.c_str(), originalFilename.c_str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static unordered_map<B2Hash, vector<std::byte>> download_data;
|
||||
@@ -364,12 +384,14 @@ static mutex updateMutex;
|
||||
|
||||
static inline void CleanupPartialUpdates()
|
||||
{
|
||||
for (update_t &update : updates)
|
||||
for (update_t &update : updates) {
|
||||
update.CleanPartialUpdate();
|
||||
}
|
||||
|
||||
for (deletion_t &deletion : deletions)
|
||||
for (deletion_t &deletion : deletions) {
|
||||
deletion.UndoRename();
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
@@ -387,10 +409,12 @@ static int Decompress(ZSTD_DCtx *ctx, std::vector<std::byte> &buf, size_t size)
|
||||
// Overwrite buffer with decompressed data
|
||||
size_t result = ZSTD_decompressDCtx(ctx, buf.data(), buf.size(), comp.data(), comp.size());
|
||||
|
||||
if (result != size)
|
||||
if (result != size) {
|
||||
return -9;
|
||||
if (ZSTD_isError(result))
|
||||
}
|
||||
if (ZSTD_isError(result)) {
|
||||
return -10;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -440,8 +464,9 @@ bool DownloadWorkerThread()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (update.state != STATE_PENDING_DOWNLOAD)
|
||||
if (update.state != STATE_PENDING_DOWNLOAD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
update.state = STATE_DOWNLOADING;
|
||||
|
||||
@@ -554,22 +579,26 @@ static inline DWORD WaitIfOBS(DWORD id, const wchar_t *expected)
|
||||
*path = 0;
|
||||
|
||||
WinHandle proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, false, id);
|
||||
if (!proc.Valid())
|
||||
if (!proc.Valid()) {
|
||||
return WAITIFOBS_WRONG_PROCESS;
|
||||
}
|
||||
|
||||
if (!QueryFullProcessImageNameW(proc, 0, path, &path_len))
|
||||
if (!QueryFullProcessImageNameW(proc, 0, path, &path_len)) {
|
||||
return WAITIFOBS_WRONG_PROCESS;
|
||||
}
|
||||
|
||||
// check it's actually our exe that's running
|
||||
size_t len = wcslen(obs_base_directory);
|
||||
if (wcsncmp(path, obs_base_directory, len) != 0)
|
||||
if (wcsncmp(path, obs_base_directory, len) != 0) {
|
||||
return WAITIFOBS_WRONG_PROCESS;
|
||||
}
|
||||
|
||||
name = wcsrchr(path, L'\\');
|
||||
if (name)
|
||||
if (name) {
|
||||
name += 1;
|
||||
else
|
||||
} else {
|
||||
name = path;
|
||||
}
|
||||
|
||||
if (_wcsnicmp(name, expected, 5) == 0) {
|
||||
HANDLE hWait[2];
|
||||
@@ -579,8 +608,9 @@ static inline DWORD WaitIfOBS(DWORD id, const wchar_t *expected)
|
||||
Log(L"Waiting for OBS PID %d at %s...", id, path);
|
||||
|
||||
int i = WaitForMultipleObjects(2, hWait, false, INFINITE);
|
||||
if (i == WAIT_OBJECT_0 + 1)
|
||||
if (i == WAIT_OBJECT_0 + 1) {
|
||||
return WAITIFOBS_CANCELLED;
|
||||
}
|
||||
|
||||
return WAITIFOBS_SUCCESS;
|
||||
}
|
||||
@@ -640,8 +670,9 @@ void HasherThread()
|
||||
|
||||
while (true) {
|
||||
ulock.lock();
|
||||
if (hashQueue.empty())
|
||||
if (hashQueue.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto fileName = hashQueue.front();
|
||||
hashQueue.pop();
|
||||
@@ -650,11 +681,13 @@ void HasherThread()
|
||||
|
||||
wchar_t updateFileName[MAX_PATH];
|
||||
|
||||
if (!UTF8ToWideBuf(updateFileName, fileName.c_str()))
|
||||
if (!UTF8ToWideBuf(updateFileName, fileName.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsSafeFilename(updateFileName))
|
||||
if (!IsSafeFilename(updateFileName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
B2Hash existingHash;
|
||||
if (CalculateFileHash(updateFileName, existingHash)) {
|
||||
@@ -698,16 +731,18 @@ static inline bool FileExists(const wchar_t *path)
|
||||
HANDLE hFind;
|
||||
|
||||
hFind = FindFirstFileW(path, &wfd);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
if (hFind != INVALID_HANDLE_VALUE) {
|
||||
FindClose(hFind);
|
||||
}
|
||||
|
||||
return hFind != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
static bool NonCorePackageInstalled(const char *name)
|
||||
{
|
||||
if (strcmp(name, "obs-browser") == 0)
|
||||
if (strcmp(name, "obs-browser") == 0) {
|
||||
return FileExists(L"obs-plugins\\64bit\\obs-browser.dll");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -715,29 +750,34 @@ static bool NonCorePackageInstalled(const char *name)
|
||||
static bool AddPackageUpdateFiles(const Package &package, const wchar_t *branch)
|
||||
{
|
||||
wchar_t wPackageName[512];
|
||||
if (!UTF8ToWideBuf(wPackageName, package.name.c_str()))
|
||||
if (!UTF8ToWideBuf(wPackageName, package.name.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (package.name != "core" && !NonCorePackageInstalled(package.name.c_str()))
|
||||
if (package.name != "core" && !NonCorePackageInstalled(package.name.c_str())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const File &file : package.files) {
|
||||
if (file.hash.size() != kBlake2StrLength)
|
||||
if (file.hash.size() != kBlake2StrLength) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The download hash may not exist if a file is uncompressed */
|
||||
|
||||
bool compressed = false;
|
||||
if (file.compressed_hash.size() == kBlake2StrLength)
|
||||
if (file.compressed_hash.size() == kBlake2StrLength) {
|
||||
compressed = true;
|
||||
}
|
||||
|
||||
/* convert strings to wide */
|
||||
|
||||
wchar_t sourceURL[1024];
|
||||
wchar_t updateFileName[MAX_PATH];
|
||||
|
||||
if (!UTF8ToWideBuf(updateFileName, file.name.c_str()))
|
||||
if (!UTF8ToWideBuf(updateFileName, file.name.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* make sure paths are safe */
|
||||
|
||||
@@ -762,8 +802,9 @@ static bool AddPackageUpdateFiles(const Package &package, const wchar_t *branch)
|
||||
|
||||
if (hashes.count(file.name)) {
|
||||
localFileHash = hashes[file.name];
|
||||
if (localFileHash == updateHash)
|
||||
if (localFileHash == updateHash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
has_hash = true;
|
||||
}
|
||||
@@ -787,8 +828,9 @@ static bool AddPackageUpdateFiles(const Package &package, const wchar_t *branch)
|
||||
}
|
||||
|
||||
update.has_hash = has_hash;
|
||||
if (has_hash)
|
||||
if (has_hash) {
|
||||
update.my_hash = localFileHash;
|
||||
}
|
||||
|
||||
updates.push_back(std::move(update));
|
||||
|
||||
@@ -802,19 +844,22 @@ static void AddPackageRemovedFiles(const Package &package)
|
||||
{
|
||||
for (const string &filename : package.removed_files) {
|
||||
wchar_t removedFileName[MAX_PATH];
|
||||
if (!UTF8ToWideBuf(removedFileName, filename.c_str()))
|
||||
if (!UTF8ToWideBuf(removedFileName, filename.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ensure paths are safe, also check if file exists */
|
||||
if (!IsSafeFilename(removedFileName))
|
||||
if (!IsSafeFilename(removedFileName)) {
|
||||
continue;
|
||||
}
|
||||
/* Technically GetFileAttributes can fail for other reasons,
|
||||
* so double-check by also checking the last error */
|
||||
if (GetFileAttributesW(removedFileName) == INVALID_FILE_ATTRIBUTES) {
|
||||
int err = GetLastError();
|
||||
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
|
||||
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
deletion_t deletion;
|
||||
deletion.originalFilename = removedFileName;
|
||||
@@ -836,8 +881,9 @@ static bool RenameRemovedFile(deletion_t &deletion)
|
||||
blake2b(hash.data(), hash.size(), junk, sizeof(junk), nullptr, 0);
|
||||
HashToString(hash, temp);
|
||||
|
||||
if (!UTF8ToWideBuf(randomStr, temp.c_str()))
|
||||
if (!UTF8ToWideBuf(randomStr, temp.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
randomStr[8] = 0;
|
||||
|
||||
@@ -861,25 +907,31 @@ static bool UpdateWithPatchIfAvailable(const PatchResponse &patch)
|
||||
wchar_t widePatchableFilename[MAX_PATH];
|
||||
wchar_t sourceURL[1024];
|
||||
|
||||
if (patch.source.compare(0, kCDNUrl.size(), kCDNUrl) != 0)
|
||||
if (patch.source.compare(0, kCDNUrl.size(), kCDNUrl) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (patch.name.find('/') == string::npos)
|
||||
if (patch.name.find('/') == string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string patchPackageName(patch.name, 0, patch.name.find('/'));
|
||||
string fileName(patch.name, patch.name.find('/') + 1);
|
||||
|
||||
if (!UTF8ToWideBuf(widePatchableFilename, fileName.c_str()))
|
||||
if (!UTF8ToWideBuf(widePatchableFilename, fileName.c_str())) {
|
||||
return false;
|
||||
if (!UTF8ToWideBuf(sourceURL, patch.source.c_str()))
|
||||
}
|
||||
if (!UTF8ToWideBuf(sourceURL, patch.source.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (update_t &update : updates) {
|
||||
if (update.packageName != patchPackageName)
|
||||
if (update.packageName != patchPackageName) {
|
||||
continue;
|
||||
if (update.outputPath != widePatchableFilename)
|
||||
}
|
||||
if (update.outputPath != widePatchableFilename) {
|
||||
continue;
|
||||
}
|
||||
|
||||
update.patchable = true;
|
||||
|
||||
@@ -911,8 +963,9 @@ static bool MoveInUseFileAway(const update_t &file)
|
||||
blake2b(hash.data(), hash.size(), junk, sizeof(junk), nullptr, 0);
|
||||
HashToString(hash, temp);
|
||||
|
||||
if (!UTF8ToWideBuf(randomStr, temp.c_str()))
|
||||
if (!UTF8ToWideBuf(randomStr, temp.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
randomStr[8] = 0;
|
||||
|
||||
@@ -956,8 +1009,9 @@ static bool UpdateFile(ZSTD_DCtx *ctx, update_t &file)
|
||||
if (curFileName) {
|
||||
curFileName[0] = '\0';
|
||||
curFileName++;
|
||||
} else
|
||||
} else {
|
||||
curFileName = baseName;
|
||||
}
|
||||
|
||||
/* Backup the existing file in case a rollback is needed */
|
||||
StringCbCopy(oldFileRenamedPath, sizeof(oldFileRenamedPath), file.outputPath.c_str());
|
||||
@@ -967,14 +1021,15 @@ static bool UpdateFile(ZSTD_DCtx *ctx, update_t &file)
|
||||
DWORD err = GetLastError();
|
||||
int is_sharing_violation = (err == ERROR_SHARING_VIOLATION || err == ERROR_USER_MAPPED_FILE);
|
||||
|
||||
if (is_sharing_violation)
|
||||
if (is_sharing_violation) {
|
||||
Status(L"Update failed: %s is still in use. "
|
||||
L"Close all programs and try again.",
|
||||
curFileName);
|
||||
else
|
||||
} else {
|
||||
Status(L"Update failed: Couldn't backup %s "
|
||||
L"(error %d)",
|
||||
curFileName, GetLastError());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1028,9 +1083,10 @@ static bool UpdateFile(ZSTD_DCtx *ctx, update_t &file)
|
||||
if (!already_tried_to_move) {
|
||||
already_tried_to_move = true;
|
||||
|
||||
if (MoveInUseFileAway(file))
|
||||
if (MoveInUseFileAway(file)) {
|
||||
goto retryAfterMovingFile;
|
||||
}
|
||||
}
|
||||
|
||||
Status(L"Update failed: %s is still in use. "
|
||||
L"Close all "
|
||||
@@ -1092,10 +1148,12 @@ static bool UpdateWorker()
|
||||
while (true) {
|
||||
ulock.lock();
|
||||
|
||||
if (updateThreadFailed)
|
||||
if (updateThreadFailed) {
|
||||
return false;
|
||||
if (updateQueue.empty())
|
||||
}
|
||||
if (updateQueue.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto update = updateQueue.front();
|
||||
updateQueue.pop();
|
||||
@@ -1120,8 +1178,9 @@ static bool UpdateWorker()
|
||||
|
||||
static bool RunUpdateWorkers(int num)
|
||||
try {
|
||||
for (update_t &update : updates)
|
||||
for (update_t &update : updates) {
|
||||
updateQueue.emplace(update);
|
||||
}
|
||||
|
||||
vector<future<bool>> thread_success_results;
|
||||
thread_success_results.resize(num);
|
||||
@@ -1274,12 +1333,14 @@ static void UpdateRegistryVersion(const Manifest &manifest)
|
||||
manifest.version_minor, manifest.version_patch);
|
||||
}
|
||||
|
||||
if (formattedLen <= 0)
|
||||
if (formattedLen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, regKey, 0, KEY_WRITE | KEY_WOW64_32KEY, &key);
|
||||
if (res != ERROR_SUCCESS)
|
||||
if (res != ERROR_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegSetValueExA(key, "DisplayVersion", 0, REG_SZ, (const BYTE *)version, formattedLen + 1);
|
||||
RegCloseKey(key);
|
||||
@@ -1310,17 +1371,20 @@ static bool Update(wchar_t *cmdLine)
|
||||
|
||||
int i = WaitForMultipleObjects(2, hWait, false, INFINITE);
|
||||
|
||||
if (i == WAIT_OBJECT_0)
|
||||
if (i == WAIT_OBJECT_0) {
|
||||
ReleaseMutex(hObsUpdateMutex);
|
||||
}
|
||||
|
||||
CloseHandle(hObsUpdateMutex);
|
||||
|
||||
if (i == WAIT_OBJECT_0 + 1)
|
||||
if (i == WAIT_OBJECT_0 + 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WaitForOBS())
|
||||
if (!WaitForOBS()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------- *
|
||||
* Init crypt stuff */
|
||||
@@ -1500,12 +1564,14 @@ static bool Update(wchar_t *cmdLine)
|
||||
|
||||
PatchesRequest files;
|
||||
for (update_t &update : updates) {
|
||||
if (!update.has_hash)
|
||||
if (!update.has_hash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char outputPath[MAX_PATH];
|
||||
if (!WideToUTF8Buf(outputPath, update.outputPath.c_str()))
|
||||
if (!WideToUTF8Buf(outputPath, update.outputPath.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string hash_string;
|
||||
HashToString(update.my_hash, hash_string);
|
||||
@@ -1535,22 +1601,25 @@ static bool Update(wchar_t *cmdLine)
|
||||
size_t result = ZSTD_compress(compressedJson.data(), compressedJson.size(), post_body.data(),
|
||||
post_body.size(), ZSTD_CLEVEL_DEFAULT);
|
||||
|
||||
if (ZSTD_isError(result))
|
||||
if (ZSTD_isError(result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
compressedJson.resize(result);
|
||||
|
||||
wstring manifestUrl(kPatchManifestURL);
|
||||
if (branch != L"stable")
|
||||
if (branch != L"stable") {
|
||||
manifestUrl += L"?branch=" + branch;
|
||||
}
|
||||
|
||||
int responseCode;
|
||||
bool success = !!HTTPPostData(manifestUrl.c_str(), (BYTE *)compressedJson.data(),
|
||||
(int)compressedJson.size(), L"Accept-Encoding: gzip", &responseCode,
|
||||
newManifest);
|
||||
|
||||
if (!success)
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (responseCode != 200) {
|
||||
Status(L"Update failed: HTTP/%d while trying to "
|
||||
@@ -1609,13 +1678,15 @@ static bool Update(wchar_t *cmdLine)
|
||||
* avoiding concurrent map mutation from multiple threads. */
|
||||
download_data.reserve(downloadHashes.size());
|
||||
for (update_t &update : updates) {
|
||||
if (update.state == STATE_PENDING_DOWNLOAD)
|
||||
if (update.state == STATE_PENDING_DOWNLOAD) {
|
||||
download_data.try_emplace(update.downloadHash);
|
||||
}
|
||||
}
|
||||
|
||||
Status(L"Downloading updates...");
|
||||
if (!RunDownloadWorkers(4))
|
||||
if (!RunDownloadWorkers(4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((size_t)completedUpdates != updates.size()) {
|
||||
Status(L"Update failed to download all files.");
|
||||
@@ -1629,8 +1700,9 @@ static bool Update(wchar_t *cmdLine)
|
||||
lastPosition = 0;
|
||||
|
||||
Status(L"Installing updates...");
|
||||
if (!RunUpdateWorkers(4))
|
||||
if (!RunUpdateWorkers(4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (deletion_t &deletion : deletions) {
|
||||
if (!RenameRemovedFile(deletion)) {
|
||||
@@ -1716,13 +1788,15 @@ static bool Update(wchar_t *cmdLine)
|
||||
/* If we get here, all updates installed successfully so we can purge
|
||||
* the old versions */
|
||||
for (update_t &update : updates) {
|
||||
if (!update.previousFile.empty())
|
||||
if (!update.previousFile.empty()) {
|
||||
DeleteFile(update.previousFile.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete all removed files mentioned in the manifest */
|
||||
for (deletion_t &deletion : deletions)
|
||||
for (deletion_t &deletion : deletions) {
|
||||
MyDeleteFile(deletion.deleteMeFilename);
|
||||
}
|
||||
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS, PBM_SETPOS, 100, 0);
|
||||
|
||||
@@ -1742,18 +1816,21 @@ static DWORD WINAPI UpdateThread(void *arg)
|
||||
* partially installed updates */
|
||||
CleanupPartialUpdates();
|
||||
|
||||
if (tempPath[0])
|
||||
if (tempPath[0]) {
|
||||
RemoveDirectory(tempPath);
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(cancelRequested, 0) == WAIT_OBJECT_0)
|
||||
if (WaitForSingleObject(cancelRequested, 0) == WAIT_OBJECT_0) {
|
||||
Status(L"Update aborted.");
|
||||
}
|
||||
|
||||
HWND hProgress = GetDlgItem(hwndMain, IDC_PROGRESS);
|
||||
|
||||
/* Even a no-op style change apparently resets the progress bar */
|
||||
LONG_PTR style = GetWindowLongPtr(hProgress, GWL_STYLE);
|
||||
if (style & PBS_MARQUEE)
|
||||
if (style & PBS_MARQUEE) {
|
||||
SetWindowLongPtr(hProgress, GWL_STYLE, style & ~PBS_MARQUEE);
|
||||
}
|
||||
|
||||
SendMessage(hProgress, PBM_SETSTATE, PBST_ERROR, 0);
|
||||
|
||||
@@ -1762,12 +1839,14 @@ static DWORD WINAPI UpdateThread(void *arg)
|
||||
|
||||
updateFailed = true;
|
||||
} else {
|
||||
if (tempPath[0])
|
||||
if (tempPath[0]) {
|
||||
RemoveDirectory(tempPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (bExiting)
|
||||
if (bExiting) {
|
||||
ExitProcess(success);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1807,8 +1886,9 @@ static void LaunchOBS(LPWSTR lpCmdLine)
|
||||
execInfo.lpDirectory = newCwd;
|
||||
execInfo.nShow = SW_SHOWNORMAL;
|
||||
|
||||
if (lpCmdLine[0])
|
||||
if (lpCmdLine[0]) {
|
||||
execInfo.lpParameters = lpCmdLine;
|
||||
}
|
||||
|
||||
ShellExecuteEx(&execInfo);
|
||||
}
|
||||
@@ -1816,8 +1896,9 @@ static void LaunchOBS(LPWSTR lpCmdLine)
|
||||
static void ToggleLogVisibility()
|
||||
{
|
||||
HWND hwndLog = GetDlgItem(hwndMain, IDC_LOG);
|
||||
if (!hwndLog)
|
||||
if (!hwndLog) {
|
||||
return;
|
||||
}
|
||||
|
||||
logVisible = !logVisible;
|
||||
|
||||
@@ -1874,8 +1955,9 @@ static INT_PTR CALLBACK UpdateDialogProc(HWND hwnd, UINT message, WPARAM wParam,
|
||||
|
||||
/* Propagate the main window font or it looks ugly */
|
||||
HFONT hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);
|
||||
if (hFont)
|
||||
if (hFont) {
|
||||
SendMessage(hwndLog, WM_SETFONT, (WPARAM)hFont, FALSE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1885,19 +1967,21 @@ static INT_PTR CALLBACK UpdateDialogProc(HWND hwnd, UINT message, WPARAM wParam,
|
||||
if (HIWORD(wParam) == BN_CLICKED) {
|
||||
DWORD result = WaitForSingleObject(updateThread, 0);
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
if (updateFailed)
|
||||
if (updateFailed) {
|
||||
PostQuitMessage(0);
|
||||
else
|
||||
} else {
|
||||
PostQuitMessage(1);
|
||||
}
|
||||
} else {
|
||||
EnableWindow((HWND)lParam, false);
|
||||
CancelUpdate(false);
|
||||
}
|
||||
}
|
||||
} else if (LOWORD(wParam) == IDC_LOGBUTTON) {
|
||||
if (HIWORD(wParam) == BN_CLICKED)
|
||||
if (HIWORD(wParam) == BN_CLICKED) {
|
||||
ToggleLogVisibility();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case WM_CLOSE:
|
||||
|
||||
@@ -38,8 +38,9 @@ static void ApplyEncoderDefaults(OBSData &settings, const obs_encoder_t *encoder
|
||||
OBSData dataRet = obs_encoder_get_defaults(encoder);
|
||||
obs_data_release(dataRet);
|
||||
|
||||
if (!!settings)
|
||||
if (!!settings) {
|
||||
obs_data_apply(dataRet, settings);
|
||||
}
|
||||
settings = std::move(dataRet);
|
||||
}
|
||||
|
||||
@@ -79,24 +80,27 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
|
||||
if (ffmpegOutput) {
|
||||
fileOutput = obs_output_create("ffmpeg_output", "adv_ffmpeg_output", nullptr, nullptr);
|
||||
if (!fileOutput)
|
||||
if (!fileOutput) {
|
||||
throw "Failed to create recording FFmpeg output "
|
||||
"(advanced output)";
|
||||
}
|
||||
} else {
|
||||
bool useReplayBuffer = config_get_bool(main->Config(), "AdvOut", "RecRB");
|
||||
if (useReplayBuffer) {
|
||||
OBSDataAutoRelease hotkey;
|
||||
const char *str = config_get_string(main->Config(), "Hotkeys", "ReplayBuffer");
|
||||
if (str)
|
||||
if (str) {
|
||||
hotkey = obs_data_create_from_json(str);
|
||||
else
|
||||
} else {
|
||||
hotkey = nullptr;
|
||||
}
|
||||
|
||||
replayBuffer = obs_output_create("replay_buffer", Str("ReplayBuffer"), nullptr, hotkey);
|
||||
|
||||
if (!replayBuffer)
|
||||
if (!replayBuffer) {
|
||||
throw "Failed to create replay buffer output "
|
||||
"(simple output)";
|
||||
}
|
||||
|
||||
signal_handler_t *signal = obs_output_get_signal_handler(replayBuffer);
|
||||
|
||||
@@ -107,30 +111,34 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
}
|
||||
|
||||
const char *mux = "ffmpeg_muxer";
|
||||
if (strcmp(recFormat, "hybrid_mp4") == 0)
|
||||
if (strcmp(recFormat, "hybrid_mp4") == 0) {
|
||||
mux = "mp4_output";
|
||||
else if (strcmp(recFormat, "hybrid_mov") == 0)
|
||||
} else if (strcmp(recFormat, "hybrid_mov") == 0) {
|
||||
mux = "mov_output";
|
||||
}
|
||||
|
||||
fileOutput = obs_output_create(mux, "adv_file_output", nullptr, nullptr);
|
||||
if (!fileOutput)
|
||||
if (!fileOutput) {
|
||||
throw "Failed to create recording output "
|
||||
"(advanced output)";
|
||||
}
|
||||
|
||||
if (!useStreamEncoder) {
|
||||
videoRecording = obs_video_encoder_create(recordEncoder, "advanced_video_recording",
|
||||
recordEncSettings, nullptr);
|
||||
if (!videoRecording)
|
||||
if (!videoRecording) {
|
||||
throw "Failed to create recording video "
|
||||
"encoder (advanced output)";
|
||||
}
|
||||
obs_encoder_release(videoRecording);
|
||||
}
|
||||
}
|
||||
|
||||
videoStreaming = obs_video_encoder_create(streamEncoder, "advanced_video_stream", streamEncSettings, nullptr);
|
||||
if (!videoStreaming)
|
||||
if (!videoStreaming) {
|
||||
throw "Failed to create streaming video encoder "
|
||||
"(advanced output)";
|
||||
}
|
||||
obs_encoder_release(videoStreaming);
|
||||
if (whipSimulcastEncoders != nullptr) {
|
||||
whipSimulcastEncoders->Create(streamEncoder, config_get_int(main->Config(), "AdvOut", "RescaleFilter"),
|
||||
@@ -141,8 +149,9 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
|
||||
const char *rate_control =
|
||||
obs_data_get_string(useStreamEncoder ? streamEncSettings : recordEncSettings, "rate_control");
|
||||
if (!rate_control)
|
||||
if (!rate_control) {
|
||||
rate_control = "";
|
||||
}
|
||||
usesBitrate = astrcmpi(rate_control, "CBR") == 0 || astrcmpi(rate_control, "VBR") == 0 ||
|
||||
astrcmpi(rate_control, "ABR") == 0;
|
||||
|
||||
@@ -175,17 +184,19 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
int streamTrackIndex = config_get_int(main->Config(), "AdvOut", "TrackIndex") - 1;
|
||||
streamAudioEnc =
|
||||
obs_audio_encoder_create(streamAudioEncoder, "adv_stream_audio", nullptr, streamTrackIndex, nullptr);
|
||||
if (!streamAudioEnc)
|
||||
if (!streamAudioEnc) {
|
||||
throw "Failed to create streaming audio encoder "
|
||||
"(advanced output)";
|
||||
}
|
||||
obs_encoder_release(streamAudioEnc);
|
||||
|
||||
id = "";
|
||||
int vodTrack = config_get_int(main->Config(), "AdvOut", "VodTrackIndex") - 1;
|
||||
streamArchiveEnc = obs_audio_encoder_create(streamAudioEncoder, ADV_ARCHIVE_NAME, nullptr, vodTrack, nullptr);
|
||||
if (!streamArchiveEnc)
|
||||
if (!streamArchiveEnc) {
|
||||
throw "Failed to create archive audio encoder "
|
||||
"(advanced output)";
|
||||
}
|
||||
obs_encoder_release(streamArchiveEnc);
|
||||
|
||||
startRecording.Connect(obs_output_get_signal_handler(fileOutput), "start", OBSStartRecording, this);
|
||||
@@ -230,14 +241,16 @@ void AdvancedOutput::UpdateStreamSettings()
|
||||
}
|
||||
|
||||
int enforced_keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
|
||||
if (keyint_sec != 0 && keyint_sec < enforced_keyint_sec)
|
||||
if (keyint_sec != 0 && keyint_sec < enforced_keyint_sec) {
|
||||
obs_data_set_int(settings, "keyint_sec", keyint_sec);
|
||||
}
|
||||
} else {
|
||||
blog(LOG_WARNING, "User is ignoring service settings.");
|
||||
}
|
||||
|
||||
if (dynBitrate && strstr(streamEncoder, "nvenc") != nullptr)
|
||||
if (dynBitrate && strstr(streamEncoder, "nvenc") != nullptr) {
|
||||
obs_data_set_bool(settings, "lookahead", false);
|
||||
}
|
||||
|
||||
video_t *video = obs_get_video();
|
||||
enum video_format format = video_output_get_format(video);
|
||||
@@ -267,8 +280,9 @@ inline void AdvancedOutput::UpdateRecordingSettings()
|
||||
void AdvancedOutput::Update()
|
||||
{
|
||||
UpdateStreamSettings();
|
||||
if (!useStreamEncoder && !ffmpegOutput)
|
||||
if (!useStreamEncoder && !ffmpegOutput) {
|
||||
UpdateRecordingSettings();
|
||||
}
|
||||
UpdateAudioSettings();
|
||||
}
|
||||
|
||||
@@ -277,8 +291,9 @@ inline bool AdvancedOutput::allowsMultiTrack()
|
||||
const char *protocol = nullptr;
|
||||
obs_service_t *service_obj = main->GetService();
|
||||
protocol = obs_service_get_protocol(service_obj);
|
||||
if (!protocol)
|
||||
if (!protocol) {
|
||||
return false;
|
||||
}
|
||||
return astrcmpi_n(protocol, SRT_PROTOCOL, strlen(SRT_PROTOCOL)) == 0 ||
|
||||
astrcmpi_n(protocol, RIST_PROTOCOL, strlen(RIST_PROTOCOL)) == 0;
|
||||
}
|
||||
@@ -335,10 +350,11 @@ inline void AdvancedOutput::SetupRecording()
|
||||
bool is_fragmented = strncmp(recFormat, "fragmented", 10) == 0;
|
||||
bool flv = strcmp(recFormat, "flv") == 0;
|
||||
|
||||
if (flv)
|
||||
if (flv) {
|
||||
tracks = config_get_int(main->Config(), "AdvOut", "FLVTrack");
|
||||
else
|
||||
} else {
|
||||
tracks = config_get_int(main->Config(), "AdvOut", "RecTracks");
|
||||
}
|
||||
|
||||
OBSDataAutoRelease settings = obs_data_create();
|
||||
unsigned int cx = 0;
|
||||
@@ -349,13 +365,15 @@ inline void AdvancedOutput::SetupRecording()
|
||||
* longer possible to select such a configuration in settings, but legacy
|
||||
* configurations might still have this configured and we don't want to
|
||||
* just break them. */
|
||||
if (tracks == 0)
|
||||
if (tracks == 0) {
|
||||
tracks = config_get_int(main->Config(), "AdvOut", "TrackIndex");
|
||||
}
|
||||
|
||||
if (useStreamEncoder) {
|
||||
obs_output_set_video_encoder(fileOutput, videoStreaming);
|
||||
if (replayBuffer)
|
||||
if (replayBuffer) {
|
||||
obs_output_set_video_encoder(replayBuffer, videoStreaming);
|
||||
}
|
||||
} else {
|
||||
if (rescaleFilter != OBS_SCALE_DISABLE && rescaleRes && *rescaleRes) {
|
||||
if (sscanf(rescaleRes, "%ux%u", &cx, &cy) != 2) {
|
||||
@@ -367,25 +385,28 @@ inline void AdvancedOutput::SetupRecording()
|
||||
obs_encoder_set_scaled_size(videoRecording, cx, cy);
|
||||
obs_encoder_set_gpu_scale_type(videoRecording, (obs_scale_type)rescaleFilter);
|
||||
obs_output_set_video_encoder(fileOutput, videoRecording);
|
||||
if (replayBuffer)
|
||||
if (replayBuffer) {
|
||||
obs_output_set_video_encoder(replayBuffer, videoRecording);
|
||||
}
|
||||
}
|
||||
|
||||
if (!flv) {
|
||||
for (int i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||
if ((tracks & (1 << i)) != 0) {
|
||||
obs_output_set_audio_encoder(fileOutput, recordTrack[i], idx);
|
||||
if (replayBuffer)
|
||||
if (replayBuffer) {
|
||||
obs_output_set_audio_encoder(replayBuffer, recordTrack[i], idx);
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
} else if (flv && tracks != 0) {
|
||||
obs_output_set_audio_encoder(fileOutput, recordTrack[tracks - 1], idx);
|
||||
|
||||
if (replayBuffer)
|
||||
if (replayBuffer) {
|
||||
obs_output_set_audio_encoder(replayBuffer, recordTrack[tracks - 1], idx);
|
||||
}
|
||||
}
|
||||
|
||||
// Use fragmented MOV/MP4 if user has not already specified custom movflags
|
||||
if (is_fragmented && (!mux || strstr(mux, "movflags") == NULL)) {
|
||||
@@ -396,17 +417,19 @@ inline void AdvancedOutput::SetupRecording()
|
||||
}
|
||||
obs_data_set_string(settings, "muxer_settings", mux_frag.c_str());
|
||||
} else {
|
||||
if (is_fragmented)
|
||||
if (is_fragmented) {
|
||||
blog(LOG_WARNING, "User enabled fragmented recording, "
|
||||
"but custom muxer settings contained movflags.");
|
||||
}
|
||||
obs_data_set_string(settings, "muxer_settings", mux);
|
||||
}
|
||||
|
||||
obs_data_set_string(settings, "path", path);
|
||||
obs_output_update(fileOutput, settings);
|
||||
if (replayBuffer)
|
||||
if (replayBuffer) {
|
||||
obs_output_update(replayBuffer, settings);
|
||||
}
|
||||
}
|
||||
|
||||
inline void AdvancedOutput::SetupFFmpeg()
|
||||
{
|
||||
@@ -519,15 +542,18 @@ inline void AdvancedOutput::UpdateAudioSettings()
|
||||
int bitrate = (int)obs_data_get_int(settings[i], "bitrate");
|
||||
obs_service_apply_encoder_settings(main->GetService(), nullptr, settings[i]);
|
||||
|
||||
if (!enforceBitrate)
|
||||
if (!enforceBitrate) {
|
||||
obs_data_set_int(settings[i], "bitrate", bitrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (track == streamTrackIndex)
|
||||
if (track == streamTrackIndex) {
|
||||
obs_encoder_update(streamAudioEnc, settings[i]);
|
||||
if (track == vodTrackIndex)
|
||||
}
|
||||
if (track == vodTrackIndex) {
|
||||
obs_encoder_update(streamArchiveEnc, settings[i]);
|
||||
}
|
||||
} else {
|
||||
obs_encoder_update(streamTrack[i], settings[i]);
|
||||
}
|
||||
@@ -537,8 +563,9 @@ inline void AdvancedOutput::UpdateAudioSettings()
|
||||
void AdvancedOutput::SetupOutputs()
|
||||
{
|
||||
obs_encoder_set_video(videoStreaming, obs_get_video());
|
||||
if (videoRecording)
|
||||
if (videoRecording) {
|
||||
obs_encoder_set_video(videoRecording, obs_get_video());
|
||||
}
|
||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||
obs_encoder_set_audio(streamTrack[i], obs_get_audio());
|
||||
obs_encoder_set_audio(recordTrack[i], obs_get_audio());
|
||||
@@ -548,11 +575,12 @@ void AdvancedOutput::SetupOutputs()
|
||||
|
||||
SetupStreaming();
|
||||
|
||||
if (ffmpegOutput)
|
||||
if (ffmpegOutput) {
|
||||
SetupFFmpeg();
|
||||
else
|
||||
} else {
|
||||
SetupRecording();
|
||||
}
|
||||
}
|
||||
|
||||
int AdvancedOutput::GetAudioBitrate(size_t i, const char *id) const
|
||||
{
|
||||
@@ -576,22 +604,25 @@ inline std::optional<size_t> AdvancedOutput::VodTrackMixerIdx(obs_service_t *ser
|
||||
} else {
|
||||
OBSDataAutoRelease settings = obs_service_get_settings(service);
|
||||
const char *service = obs_data_get_string(settings, "service");
|
||||
if (!ServiceSupportsVodTrack(service))
|
||||
if (!ServiceSupportsVodTrack(service)) {
|
||||
vodTrackEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (vodTrackEnabled && streamTrackIndex != vodTrackIndex)
|
||||
if (vodTrackEnabled && streamTrackIndex != vodTrackIndex) {
|
||||
return {vodTrackIndex - 1};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline void AdvancedOutput::SetupVodTrack(obs_service_t *service)
|
||||
{
|
||||
if (VodTrackMixerIdx(service).has_value())
|
||||
if (VodTrackMixerIdx(service).has_value()) {
|
||||
obs_output_set_audio_encoder(streamOutput, streamArchiveEnc, 1);
|
||||
else
|
||||
} else {
|
||||
clear_archive_encoder(streamOutput, ADV_ARCHIVE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_future<void> AdvancedOutput::SetupStreaming(obs_service_t *service,
|
||||
SetupStreamingContinuation_t continuation)
|
||||
@@ -606,12 +637,14 @@ std::shared_future<void> AdvancedOutput::SetupStreaming(obs_service_t *service,
|
||||
|
||||
UpdateAudioSettings();
|
||||
|
||||
if (!Active())
|
||||
if (!Active()) {
|
||||
SetupOutputs();
|
||||
}
|
||||
|
||||
Auth *auth = main->GetAuth();
|
||||
if (auth)
|
||||
if (auth) {
|
||||
auth->OnStreamConfig();
|
||||
}
|
||||
|
||||
/* --------------------- */
|
||||
|
||||
@@ -626,8 +659,9 @@ std::shared_future<void> AdvancedOutput::SetupStreaming(obs_service_t *service,
|
||||
|
||||
auto handle_multitrack_video_result = [this, type = std::string{type}, is_multitrack_output,
|
||||
multiTrackAudioMixes](std::optional<bool> multitrackVideoResult) {
|
||||
if (multitrackVideoResult.has_value())
|
||||
if (multitrackVideoResult.has_value()) {
|
||||
return multitrackVideoResult.value();
|
||||
}
|
||||
|
||||
/* XXX: this is messy and disgusting and should be refactored */
|
||||
if (outputType != type) {
|
||||
@@ -704,9 +738,10 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
||||
obs_service_t *service_obj = main->GetService();
|
||||
const char *protocol = obs_service_get_protocol(service_obj);
|
||||
if (protocol) {
|
||||
if (astrcmpi_n(protocol, RTMP_PROTOCOL, strlen(RTMP_PROTOCOL)) == 0)
|
||||
if (astrcmpi_n(protocol, RTMP_PROTOCOL, strlen(RTMP_PROTOCOL)) == 0) {
|
||||
is_rtmp = true;
|
||||
}
|
||||
}
|
||||
|
||||
OBSDataAutoRelease settings = obs_data_create();
|
||||
obs_data_set_string(settings, "bind_ip", bindIP);
|
||||
@@ -721,8 +756,9 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
||||
|
||||
obs_output_update(streamOutput, settings);
|
||||
|
||||
if (!reconnect)
|
||||
if (!reconnect) {
|
||||
maxRetries = 0;
|
||||
}
|
||||
|
||||
obs_output_set_delay(streamOutput, useDelay ? delaySec : 0, preserveDelay ? OBS_OUTPUT_DELAY_PRESERVE : 0);
|
||||
|
||||
@@ -731,20 +767,23 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
||||
SetupVodTrack(service);
|
||||
}
|
||||
if (obs_output_start(streamOutput)) {
|
||||
if (multitrackVideo && multitrackVideoActive)
|
||||
if (multitrackVideo && multitrackVideoActive) {
|
||||
multitrackVideo->StartedStreaming();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (multitrackVideo && multitrackVideoActive)
|
||||
if (multitrackVideo && multitrackVideoActive) {
|
||||
multitrackVideoActive = false;
|
||||
}
|
||||
|
||||
const char *error = obs_output_get_last_error(streamOutput);
|
||||
bool hasLastError = error && *error;
|
||||
if (hasLastError)
|
||||
if (hasLastError) {
|
||||
lastError = error;
|
||||
else
|
||||
} else {
|
||||
lastError = string();
|
||||
}
|
||||
|
||||
const char *type = obs_output_get_id(streamOutput);
|
||||
blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type, hasLastError ? " Last Error: " : "",
|
||||
@@ -774,8 +813,9 @@ bool AdvancedOutput::StartRecording()
|
||||
|
||||
UpdateAudioSettings();
|
||||
|
||||
if (!Active())
|
||||
if (!Active()) {
|
||||
SetupOutputs();
|
||||
}
|
||||
|
||||
if (!ffmpegOutput || ffmpegRecording) {
|
||||
path = config_get_string(main->Config(), "AdvOut", ffmpegRecording ? "FFFilePath" : "RecFilePath");
|
||||
@@ -817,10 +857,11 @@ bool AdvancedOutput::StartRecording()
|
||||
if (!obs_output_start(fileOutput)) {
|
||||
QString error_reason;
|
||||
const char *error = obs_output_get_last_error(fileOutput);
|
||||
if (error)
|
||||
if (error) {
|
||||
error_reason = QT_UTF8(error);
|
||||
else
|
||||
} else {
|
||||
error_reason = QTStr("Output.StartFailedGeneric");
|
||||
}
|
||||
QMessageBox::critical(main, QTStr("Output.StartRecordingFailed"), error_reason);
|
||||
return false;
|
||||
}
|
||||
@@ -841,16 +882,18 @@ bool AdvancedOutput::StartReplayBuffer()
|
||||
int rbSize;
|
||||
|
||||
if (!useStreamEncoder) {
|
||||
if (!ffmpegOutput)
|
||||
if (!ffmpegOutput) {
|
||||
UpdateRecordingSettings();
|
||||
}
|
||||
} else if (!obs_output_active(StreamingOutput())) {
|
||||
UpdateStreamSettings();
|
||||
}
|
||||
|
||||
UpdateAudioSettings();
|
||||
|
||||
if (!Active())
|
||||
if (!Active()) {
|
||||
SetupOutputs();
|
||||
}
|
||||
|
||||
if (!ffmpegOutput || ffmpegRecording) {
|
||||
path = config_get_string(main->Config(), "AdvOut", ffmpegRecording ? "FFFilePath" : "RecFilePath");
|
||||
@@ -882,10 +925,11 @@ bool AdvancedOutput::StartReplayBuffer()
|
||||
if (!obs_output_start(replayBuffer)) {
|
||||
QString error_reason;
|
||||
const char *error = obs_output_get_last_error(replayBuffer);
|
||||
if (error)
|
||||
if (error) {
|
||||
error_reason = QT_UTF8(error);
|
||||
else
|
||||
} else {
|
||||
error_reason = QTStr("Output.StartFailedGeneric");
|
||||
}
|
||||
QMessageBox::critical(main, QTStr("Output.StartReplayFailed"), error_reason);
|
||||
return false;
|
||||
}
|
||||
@@ -896,29 +940,32 @@ bool AdvancedOutput::StartReplayBuffer()
|
||||
void AdvancedOutput::StopStreaming(bool force)
|
||||
{
|
||||
auto output = StreamingOutput();
|
||||
if (force && output)
|
||||
if (force && output) {
|
||||
obs_output_force_stop(output);
|
||||
else if (multitrackVideo && multitrackVideoActive)
|
||||
} else if (multitrackVideo && multitrackVideoActive) {
|
||||
multitrackVideo->StopStreaming();
|
||||
else
|
||||
} else {
|
||||
obs_output_stop(output);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvancedOutput::StopRecording(bool force)
|
||||
{
|
||||
if (force)
|
||||
if (force) {
|
||||
obs_output_force_stop(fileOutput);
|
||||
else
|
||||
} else {
|
||||
obs_output_stop(fileOutput);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvancedOutput::StopReplayBuffer(bool force)
|
||||
{
|
||||
if (force)
|
||||
if (force) {
|
||||
obs_output_force_stop(replayBuffer);
|
||||
else
|
||||
} else {
|
||||
obs_output_stop(replayBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool AdvancedOutput::StreamingActive() const
|
||||
{
|
||||
|
||||
@@ -54,9 +54,10 @@ try {
|
||||
json manifestContents = json::parse(manifest_data);
|
||||
Manifest manifest = manifestContents.get<Manifest>();
|
||||
|
||||
if (manifest.version_major == 0 && manifest.commit.empty())
|
||||
if (manifest.version_major == 0 && manifest.commit.empty()) {
|
||||
throw strprintf("Invalid version number: %d.%d.%d", manifest.version_major, manifest.version_minor,
|
||||
manifest.version_patch);
|
||||
}
|
||||
|
||||
notes = manifest.notes;
|
||||
|
||||
@@ -67,19 +68,21 @@ try {
|
||||
new_ver <<= 16;
|
||||
/* RC builds are shifted so that rc1 and beta1 versions do not result
|
||||
* in the same new_ver. */
|
||||
if (manifest.rc > 0)
|
||||
if (manifest.rc > 0) {
|
||||
new_ver |= (uint64_t)manifest.rc << 8;
|
||||
else if (manifest.beta > 0)
|
||||
} else if (manifest.beta > 0) {
|
||||
new_ver |= (uint64_t)manifest.beta;
|
||||
}
|
||||
|
||||
updateVer = to_string(new_ver);
|
||||
|
||||
/* When using a pre-release build or non-default branch we only check if
|
||||
* the manifest version is different, so that it can be rolled back. */
|
||||
if (branch != WIN_DEFAULT_BRANCH || isPreRelease)
|
||||
if (branch != WIN_DEFAULT_BRANCH || isPreRelease) {
|
||||
*updatesAvailable = new_ver != currentVersion;
|
||||
else
|
||||
} else {
|
||||
*updatesAvailable = new_ver > currentVersion;
|
||||
}
|
||||
} else {
|
||||
/* Test or nightly builds may not have a (valid) version number,
|
||||
* so compare commit hashes instead. */
|
||||
@@ -99,13 +102,15 @@ try {
|
||||
bool GetBranchAndUrl(string &selectedBranch, string &manifestUrl)
|
||||
{
|
||||
const char *config_branch = config_get_string(App()->GetAppConfig(), "General", "UpdateBranch");
|
||||
if (!config_branch)
|
||||
if (!config_branch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (const UpdateBranch &branch : App()->GetBranches()) {
|
||||
if (branch.name != config_branch)
|
||||
if (branch.name != config_branch) {
|
||||
continue;
|
||||
}
|
||||
/* A branch that is found but disabled will just silently fall back to
|
||||
* the default. But if the branch was removed entirely, the user should
|
||||
* be warned, so leave this false *only* if the branch was removed. */
|
||||
@@ -183,8 +188,9 @@ try {
|
||||
/* ----------------------------------- *
|
||||
* get branches from server */
|
||||
|
||||
if (FetchAndVerifyFile("branches", "obs-studio\\updates\\branches.json", WIN_BRANCHES_URL, &text))
|
||||
if (FetchAndVerifyFile("branches", "obs-studio\\updates\\branches.json", WIN_BRANCHES_URL, &text)) {
|
||||
App()->SetBranchData(text);
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* check branch and get manifest url */
|
||||
@@ -196,16 +202,18 @@ try {
|
||||
|
||||
/* allow server to know if this was a manual update check in case
|
||||
* we want to allow people to bypass a configured rollout rate */
|
||||
if (manualUpdate)
|
||||
if (manualUpdate) {
|
||||
extraHeaders.emplace_back("X-OBS2-ManualUpdate: 1");
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* get manifest from server */
|
||||
|
||||
text.clear();
|
||||
if (!FetchAndVerifyFile("manifest", "obs-studio\\updates\\manifest.json", manifestUrl.c_str(), &text,
|
||||
extraHeaders))
|
||||
extraHeaders)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* check manifest for update */
|
||||
@@ -213,12 +221,14 @@ try {
|
||||
string notes;
|
||||
string updateVer;
|
||||
|
||||
if (!ParseUpdateManifest(text.c_str(), &updatesAvailable, notes, updateVer, branch))
|
||||
if (!ParseUpdateManifest(text.c_str(), &updatesAvailable, notes, updateVer, branch)) {
|
||||
throw string("Failed to parse manifest");
|
||||
}
|
||||
|
||||
if (!updatesAvailable && !repairMode) {
|
||||
if (manualUpdate)
|
||||
if (manualUpdate) {
|
||||
info(QTStr("Updater.NoUpdatesAvailable.Title"), QTStr("Updater.NoUpdatesAvailable.Text"));
|
||||
}
|
||||
return;
|
||||
} else if (updatesAvailable && repairMode) {
|
||||
info(QTStr("Updater.RepairButUpdatesAvailable.Title"), QTStr("Updater.RepairButUpdatesAvailable.Text"));
|
||||
@@ -229,21 +239,24 @@ try {
|
||||
* skip this version if set to skip */
|
||||
|
||||
const char *skipUpdateVer = config_get_string(App()->GetAppConfig(), "General", "SkipUpdateVersion");
|
||||
if (!manualUpdate && !repairMode && skipUpdateVer && updateVer == skipUpdateVer)
|
||||
if (!manualUpdate && !repairMode && skipUpdateVer && updateVer == skipUpdateVer) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* fetch updater module */
|
||||
|
||||
if (!FetchAndVerifyFile("updater", "obs-studio\\updates\\updater.exe", WIN_UPDATER_URL, nullptr))
|
||||
if (!FetchAndVerifyFile("updater", "obs-studio\\updates\\updater.exe", WIN_UPDATER_URL, nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* query user for update */
|
||||
|
||||
if (repairMode) {
|
||||
if (!queryRepair())
|
||||
if (!queryRepair()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
int queryResult = queryUpdate(manualUpdate, notes.c_str());
|
||||
|
||||
@@ -266,8 +279,9 @@ try {
|
||||
wchar_t cwd[MAX_PATH];
|
||||
GetModuleFileNameW(nullptr, cwd, _countof(cwd) - 1);
|
||||
wchar_t *p = wcsrchr(cwd, '\\');
|
||||
if (p)
|
||||
if (p) {
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* execute updater */
|
||||
@@ -276,8 +290,9 @@ try {
|
||||
BPtr<wchar_t> wUpdateFilePath;
|
||||
|
||||
size_t size = os_utf8_to_wcs_ptr(updateFilePath, 0, &wUpdateFilePath);
|
||||
if (!size)
|
||||
if (!size) {
|
||||
throw string("Could not convert updateFilePath to wide");
|
||||
}
|
||||
|
||||
/* note, can't use CreateProcess to launch as admin. */
|
||||
SHELLEXECUTEINFO execInfo = {};
|
||||
@@ -286,13 +301,15 @@ try {
|
||||
execInfo.lpFile = wUpdateFilePath;
|
||||
|
||||
string parameters;
|
||||
if (branch != WIN_DEFAULT_BRANCH)
|
||||
if (branch != WIN_DEFAULT_BRANCH) {
|
||||
parameters += "--branch=" + branch;
|
||||
}
|
||||
|
||||
obs_cmdline_args obs_args = obs_get_cmdline_args();
|
||||
for (int idx = 1; idx < obs_args.argc; idx++) {
|
||||
if (!parameters.empty())
|
||||
if (!parameters.empty()) {
|
||||
parameters += " ";
|
||||
}
|
||||
|
||||
parameters += obs_args.argv[idx];
|
||||
}
|
||||
@@ -300,15 +317,17 @@ try {
|
||||
/* Portable mode can be enabled via sentinel files, so copying the
|
||||
* command line doesn't guarantee the flag to be there. */
|
||||
if (App()->IsPortableMode() && parameters.find("--portable") == string::npos) {
|
||||
if (!parameters.empty())
|
||||
if (!parameters.empty()) {
|
||||
parameters += " ";
|
||||
}
|
||||
parameters += "--portable";
|
||||
}
|
||||
|
||||
BPtr<wchar_t> lpParameters;
|
||||
size = os_utf8_to_wcs_ptr(parameters.c_str(), 0, &lpParameters);
|
||||
if (!size && !parameters.empty())
|
||||
if (!size && !parameters.empty()) {
|
||||
throw string("Could not convert parameters to wide");
|
||||
}
|
||||
|
||||
execInfo.lpParameters = lpParameters;
|
||||
execInfo.lpDirectory = cwd;
|
||||
|
||||
@@ -27,8 +27,9 @@ void OBSStreamStarting(void *data, calldata_t *params)
|
||||
obs_output_t *obj = (obs_output_t *)calldata_ptr(params, "output");
|
||||
|
||||
int sec = (int)obs_output_get_active_delay(obj);
|
||||
if (sec == 0)
|
||||
if (sec == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
output->delayActive = true;
|
||||
QMetaObject::invokeMethod(output->main, "StreamDelayStarting", Q_ARG(int, sec));
|
||||
@@ -40,11 +41,12 @@ void OBSStreamStopping(void *data, calldata_t *params)
|
||||
obs_output_t *obj = (obs_output_t *)calldata_ptr(params, "output");
|
||||
|
||||
int sec = (int)obs_output_get_active_delay(obj);
|
||||
if (sec == 0)
|
||||
if (sec == 0) {
|
||||
QMetaObject::invokeMethod(output->main, "StreamStopping");
|
||||
else
|
||||
} else {
|
||||
QMetaObject::invokeMethod(output->main, "StreamDelayStopping", Q_ARG(int, sec));
|
||||
}
|
||||
}
|
||||
|
||||
void OBSStartStreaming(void *data, calldata_t * /* params */)
|
||||
{
|
||||
@@ -192,8 +194,9 @@ const char *GetStreamOutputType(const obs_service_t *service)
|
||||
/* Check if the service has a preferred output type */
|
||||
output = obs_service_get_preferred_output_type(service);
|
||||
if (output) {
|
||||
if ((obs_get_output_flags(output) & OBS_OUTPUT_SERVICE) != 0)
|
||||
if ((obs_get_output_flags(output) & OBS_OUTPUT_SERVICE) != 0) {
|
||||
return output;
|
||||
}
|
||||
|
||||
blog(LOG_WARNING, "The output '%s' is not registered, fallback to another one", output);
|
||||
}
|
||||
@@ -209,8 +212,9 @@ const char *GetStreamOutputType(const obs_service_t *service)
|
||||
|
||||
/* If third-party protocol, use the first enumerated type */
|
||||
obs_enum_output_types_with_protocol(protocol, &output, return_first_id);
|
||||
if (output)
|
||||
if (output) {
|
||||
return output;
|
||||
}
|
||||
|
||||
blog(LOG_WARNING, "No output compatible with the service '%s' is registered", obs_service_get_id(service));
|
||||
|
||||
@@ -234,37 +238,43 @@ BasicOutputHandler::BasicOutputHandler(OBSBasic *main_) : main(main_)
|
||||
(obs_data_has_user_value(settings, "multitrack_video_configuration_url") ||
|
||||
strcmp(obs_service_get_id(service), "rtmp_custom") == 0);
|
||||
|
||||
if (multitrack_enabled)
|
||||
if (multitrack_enabled) {
|
||||
multitrackVideo = make_unique<MultitrackVideoOutput>();
|
||||
}
|
||||
|
||||
if (config_get_int(main->Config(), "Stream1", "WHIPSimulcastTotalLayers") > 1)
|
||||
if (config_get_int(main->Config(), "Stream1", "WHIPSimulcastTotalLayers") > 1) {
|
||||
whipSimulcastEncoders = make_unique<WHIPSimulcastEncoders>();
|
||||
}
|
||||
}
|
||||
|
||||
extern void log_vcam_changed(const VCamConfig &config, bool starting);
|
||||
|
||||
bool BasicOutputHandler::StartVirtualCam()
|
||||
{
|
||||
if (!main->vcamEnabled)
|
||||
if (!main->vcamEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool typeIsProgram = main->vcamConfig.type == VCamOutputType::ProgramView;
|
||||
|
||||
if (!virtualCamView && !typeIsProgram)
|
||||
if (!virtualCamView && !typeIsProgram) {
|
||||
virtualCamView = obs_view_create();
|
||||
}
|
||||
|
||||
UpdateVirtualCamOutputSource();
|
||||
|
||||
if (!virtualCamVideo) {
|
||||
virtualCamVideo = typeIsProgram ? obs_get_video() : obs_view_add(virtualCamView);
|
||||
|
||||
if (!virtualCamVideo)
|
||||
if (!virtualCamVideo) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
obs_output_set_media(virtualCam, virtualCamVideo, obs_get_audio());
|
||||
if (!Active())
|
||||
if (!Active()) {
|
||||
SetupOutputs();
|
||||
}
|
||||
|
||||
bool success = obs_output_start(virtualCam);
|
||||
if (!success) {
|
||||
@@ -304,8 +314,9 @@ bool BasicOutputHandler::VirtualCamActive() const
|
||||
|
||||
void BasicOutputHandler::UpdateVirtualCamOutputSource()
|
||||
{
|
||||
if (!main->vcamEnabled || !virtualCamView)
|
||||
if (!main->vcamEnabled || !virtualCamView) {
|
||||
return;
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease source;
|
||||
|
||||
@@ -328,8 +339,9 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource()
|
||||
case VCamOutputType::SourceOutput:
|
||||
OBSSourceAutoRelease s = obs_get_source_by_name(main->vcamConfig.source.c_str());
|
||||
|
||||
if (!vCamSourceScene)
|
||||
if (!vCamSourceScene) {
|
||||
vCamSourceScene = obs_scene_create_private("vcam_source");
|
||||
}
|
||||
source = obs_source_get_ref(obs_scene_get_source(vCamSourceScene));
|
||||
|
||||
if (vCamSourceSceneItem && (obs_sceneitem_get_source(vCamSourceSceneItem) != s)) {
|
||||
@@ -353,9 +365,10 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource()
|
||||
}
|
||||
|
||||
OBSSourceAutoRelease current = obs_view_get_source(virtualCamView, 0);
|
||||
if (source != current)
|
||||
if (source != current) {
|
||||
obs_view_set_source(virtualCamView, 0, source);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicOutputHandler::DestroyVirtualCamView()
|
||||
{
|
||||
@@ -376,8 +389,9 @@ void BasicOutputHandler::DestroyVirtualCamView()
|
||||
|
||||
void BasicOutputHandler::DestroyVirtualCameraScene()
|
||||
{
|
||||
if (!vCamSourceScene)
|
||||
if (!vCamSourceScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_scene_release(vCamSourceScene);
|
||||
vCamSourceScene = nullptr;
|
||||
@@ -411,22 +425,25 @@ void clear_archive_encoder(obs_output_t *output, const char *expected_name)
|
||||
obs_encoder_release(last);
|
||||
}
|
||||
|
||||
if (clear)
|
||||
if (clear) {
|
||||
obs_output_set_audio_encoder(output, nullptr, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicOutputHandler::SetupAutoRemux(const char *&container)
|
||||
{
|
||||
bool autoRemux = config_get_bool(main->Config(), "Video", "AutoRemux");
|
||||
if (autoRemux && strcmp(container, "mp4") == 0)
|
||||
if (autoRemux && strcmp(container, "mp4") == 0) {
|
||||
container = "mkv";
|
||||
}
|
||||
}
|
||||
|
||||
std::string BasicOutputHandler::GetRecordingFilename(const char *path, const char *container, bool noSpace,
|
||||
bool overwrite, const char *format, bool ffmpeg)
|
||||
{
|
||||
if (!ffmpeg)
|
||||
if (!ffmpeg) {
|
||||
SetupAutoRemux(container);
|
||||
}
|
||||
|
||||
string dst = GetOutputFilename(path, container, noSpace, overwrite, format);
|
||||
lastRecordingPath = dst;
|
||||
@@ -456,9 +473,10 @@ std::shared_future<void> BasicOutputHandler::SetupMultitrackVideo(obs_service_t
|
||||
bool is_custom = strncmp("rtmp_custom", obs_service_get_type(service), 11) == 0;
|
||||
|
||||
std::optional<std::string> custom_config = std::nullopt;
|
||||
if (config_get_bool(main->Config(), "Stream1", "MultitrackVideoConfigOverrideEnabled"))
|
||||
if (config_get_bool(main->Config(), "Stream1", "MultitrackVideoConfigOverrideEnabled")) {
|
||||
custom_config = DeserializeConfigText(
|
||||
config_get_string(main->Config(), "Stream1", "MultitrackVideoConfigOverride"));
|
||||
}
|
||||
|
||||
std::optional<QString> extraCanvasUUID;
|
||||
const char *uuid = config_get_string(main->Config(), "Stream1", "MultitrackExtraCanvas");
|
||||
@@ -515,8 +533,9 @@ std::shared_future<void> BasicOutputHandler::SetupMultitrackVideo(obs_service_t
|
||||
}
|
||||
|
||||
multitrackVideoActive = false;
|
||||
if (!error->ShowDialog(main, multitrack_video_name))
|
||||
if (!error->ShowDialog(main, multitrack_video_name)) {
|
||||
return continuation(false);
|
||||
}
|
||||
return continuation(std::nullopt);
|
||||
}
|
||||
|
||||
@@ -557,8 +576,9 @@ OBSDataAutoRelease BasicOutputHandler::GenerateMultitrackVideoStreamDumpConfig()
|
||||
{
|
||||
auto stream_dump_enabled = config_get_bool(main->Config(), "Stream1", "MultitrackVideoStreamDumpEnabled");
|
||||
|
||||
if (!stream_dump_enabled)
|
||||
if (!stream_dump_enabled) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *path = config_get_string(main->Config(), "SimpleOutput", "FilePath");
|
||||
bool noSpace = config_get_bool(main->Config(), "SimpleOutput", "FileNameWithoutSpace");
|
||||
|
||||
@@ -139,9 +139,10 @@ inline bool ServiceSupportsVodTrack(const char *service)
|
||||
static const char *vodTrackServices[] = {"Twitch"};
|
||||
|
||||
for (const char *vodTrackService : vodTrackServices) {
|
||||
if (astrcmpi(vodTrackService, service) == 0)
|
||||
if (astrcmpi(vodTrackService, service) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,9 @@ void ExtraBrowsersDelegate::setEditorData(QWidget *editor, const QModelIndex &in
|
||||
bool ExtraBrowsersDelegate::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
QLineEdit *edit = qobject_cast<QLineEdit *>(object);
|
||||
if (!edit)
|
||||
if (!edit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LineEditCanceled(event)) {
|
||||
RevertText(edit);
|
||||
|
||||
@@ -43,8 +43,9 @@ QVariant ExtraBrowsersModel::data(const QModelIndex &index, int role) const
|
||||
int count = items.size();
|
||||
bool validRole = role == Qt::DisplayRole || role == Qt::AccessibleTextRole;
|
||||
|
||||
if (!validRole)
|
||||
if (!validRole) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (idx >= 0 && idx < count) {
|
||||
switch (column) {
|
||||
@@ -85,8 +86,9 @@ Qt::ItemFlags ExtraBrowsersModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractTableModel::flags(index);
|
||||
|
||||
if (index.column() != (int)Column::Delete)
|
||||
if (index.column() != (int)Column::Delete) {
|
||||
flags |= Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -109,8 +111,9 @@ void ExtraBrowsersModel::AddDeleteButton(int idx)
|
||||
|
||||
void ExtraBrowsersModel::CheckToAdd()
|
||||
{
|
||||
if (newTitle.isEmpty() || newURL.isEmpty())
|
||||
if (newTitle.isEmpty() || newURL.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = items.size() + 1;
|
||||
beginInsertRows(QModelIndex(), idx, idx);
|
||||
@@ -201,8 +204,9 @@ void ExtraBrowsersModel::Apply()
|
||||
main->extraBrowserDocks.removeAt(idx);
|
||||
}
|
||||
|
||||
if (main->extraBrowserDocks.empty())
|
||||
if (main->extraBrowserDocks.empty()) {
|
||||
main->extraBrowserMenuDocksSeparator.clear();
|
||||
}
|
||||
|
||||
deleted.clear();
|
||||
|
||||
@@ -249,6 +253,7 @@ void ExtraBrowsersModel::TabSelection(bool forward)
|
||||
|
||||
void ExtraBrowsersModel::Init()
|
||||
{
|
||||
for (int i = 0; i < items.count(); i++)
|
||||
for (int i = 0; i < items.count(); i++) {
|
||||
AddDeleteButton(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,9 @@ vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format, bool ignore_comp
|
||||
|
||||
while ((codec = av_codec_iterate(&i)) != nullptr) {
|
||||
// Not an encoding codec
|
||||
if (!av_codec_is_encoder(codec))
|
||||
if (!av_codec_is_encoder(codec)) {
|
||||
continue;
|
||||
}
|
||||
// Skip if not supported and compatibility check not disabled
|
||||
if (!ignore_compatibility && !av_codec_get_tag(format.codec_tags, codec->id)) {
|
||||
continue;
|
||||
@@ -46,16 +47,19 @@ vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format, bool ignore_comp
|
||||
|
||||
bool FFCodecAndFormatCompatible(const char *codec, const char *format)
|
||||
{
|
||||
if (!codec || !format)
|
||||
if (!codec || !format) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const AVOutputFormat *output_format = av_guess_format(format, nullptr, nullptr);
|
||||
if (!output_format)
|
||||
if (!output_format) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const AVCodecDescriptor *codec_desc = avcodec_descriptor_get_by_name(codec);
|
||||
if (!codec_desc)
|
||||
if (!codec_desc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return avformat_query_codec(output_format, codec_desc->id, FF_COMPLIANCE_NORMAL) == 1;
|
||||
}
|
||||
@@ -171,13 +175,15 @@ static const unordered_map<string, unordered_set<string>> codec_compat = {
|
||||
bool ContainerSupportsCodec(const string &container, const string &codec)
|
||||
{
|
||||
auto iter = codec_compat.find(container);
|
||||
if (iter == codec_compat.end())
|
||||
if (iter == codec_compat.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto codecs = iter->second;
|
||||
// Assume everything is supported
|
||||
if (codecs.empty())
|
||||
if (codecs.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return codecs.count(codec) > 0;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,9 @@ struct FFmpegCodec {
|
||||
|
||||
bool operator==(const FFmpegCodec &codec) const
|
||||
{
|
||||
if (id != codec.id)
|
||||
if (id != codec.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strequal(name, codec.name);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,9 @@ using namespace std;
|
||||
|
||||
static bool is_output_device(const AVClass *avclass)
|
||||
{
|
||||
if (!avclass)
|
||||
if (!avclass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (avclass->category) {
|
||||
case AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT:
|
||||
@@ -42,8 +43,9 @@ vector<FFmpegFormat> GetSupportedFormats()
|
||||
|
||||
void *i = 0;
|
||||
while ((output_format = av_muxer_iterate(&i)) != nullptr) {
|
||||
if (is_output_device(output_format->priv_class))
|
||||
if (is_output_device(output_format->priv_class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
formats.emplace_back(output_format);
|
||||
}
|
||||
@@ -54,11 +56,13 @@ vector<FFmpegFormat> GetSupportedFormats()
|
||||
FFmpegCodec FFmpegFormat::GetDefaultEncoder(FFmpegCodecType codec_type) const
|
||||
{
|
||||
const AVCodecID codec_id = codec_type == VIDEO ? video_codec : audio_codec;
|
||||
if (codec_type == UNKNOWN || codec_id == AV_CODEC_ID_NONE)
|
||||
if (codec_type == UNKNOWN || codec_id == AV_CODEC_ID_NONE) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto codec = avcodec_find_encoder(codec_id))
|
||||
if (auto codec = avcodec_find_encoder(codec_id)) {
|
||||
return {codec};
|
||||
}
|
||||
|
||||
/* Fall back to using the format name as the encoder,
|
||||
* this works for some formats such as FLV. */
|
||||
|
||||
@@ -67,8 +67,9 @@ struct FFmpegFormat {
|
||||
|
||||
bool operator==(const FFmpegFormat &format) const
|
||||
{
|
||||
if (!strequal(name, format.name))
|
||||
if (!strequal(name, format.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strequal(mime_type, format.mime_type);
|
||||
}
|
||||
|
||||
@@ -28,14 +28,18 @@ enum FFmpegCodecType { AUDIO, VIDEO, UNKNOWN };
|
||||
*/
|
||||
static bool strequal(const char *a, const char *b)
|
||||
{
|
||||
if (!a && !b)
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
if (!a && *b == 0)
|
||||
}
|
||||
if (!a && *b == 0) {
|
||||
return true;
|
||||
if (!b && *a == 0)
|
||||
}
|
||||
if (!b && *a == 0) {
|
||||
return true;
|
||||
if (!a || !b)
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
|
||||
@@ -67,8 +67,9 @@ using json = nlohmann::json;
|
||||
|
||||
void censorRecurse(json &data)
|
||||
{
|
||||
if (!data.is_structured())
|
||||
if (!data.is_structured()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = data.find("authentication");
|
||||
if (it != data.end() && it->is_string()) {
|
||||
|
||||
@@ -22,12 +22,14 @@ void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json, const GoLiveAp
|
||||
{
|
||||
using GoLiveApi::StatusResult;
|
||||
|
||||
if (!config.status)
|
||||
if (!config.status) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &status = *config.status;
|
||||
if (status.result == StatusResult::Success)
|
||||
if (status.result == StatusResult::Success) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto warn_continue = [&](QString message) {
|
||||
bool ret = false;
|
||||
@@ -44,8 +46,9 @@ void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json, const GoLiveAp
|
||||
return mb.exec() == QMessageBox::StandardButton::No;
|
||||
},
|
||||
BlockingConnectionTypeFor(parent), &ret);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
throw MultitrackVideoError::cancel();
|
||||
}
|
||||
};
|
||||
|
||||
auto missing_html = [] {
|
||||
@@ -73,8 +76,9 @@ GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url, const GoLiv
|
||||
json post_data_json = post_data;
|
||||
blog(LOG_INFO, "Go live POST data: %s", censoredJson(post_data_json).toUtf8().constData());
|
||||
|
||||
if (url.isEmpty())
|
||||
if (url.isEmpty()) {
|
||||
throw MultitrackVideoError::critical(QTStr("FailedToStartStream.MissingConfigURL"));
|
||||
}
|
||||
|
||||
std::string encodeConfigText;
|
||||
std::string libraryError;
|
||||
@@ -89,9 +93,10 @@ GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url, const GoLiv
|
||||
nullptr, // signature
|
||||
5); // timeout in seconds
|
||||
|
||||
if (!encodeConfigDownloadedOk)
|
||||
if (!encodeConfigDownloadedOk) {
|
||||
throw MultitrackVideoError::warning(
|
||||
QTStr("FailedToStartStream.ConfigRequestFailed").arg(url, libraryError.c_str()));
|
||||
}
|
||||
try {
|
||||
auto data = json::parse(encodeConfigText);
|
||||
blog(LOG_INFO, "Go live response data: %s", censoredJson(data, true).toUtf8().constData());
|
||||
|
||||
@@ -24,8 +24,9 @@ GoLiveApi::PostData constructGoLivePost(QString streamKey, const std::optional<u
|
||||
const char *encoder_id = nullptr;
|
||||
for (size_t i = 0; obs_enum_encoder_types(i, &encoder_id); i++) {
|
||||
auto codec = obs_get_encoder_codec(encoder_id);
|
||||
if (!codec)
|
||||
if (!codec) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (qstricmp(codec, "h264") == 0) {
|
||||
client.supported_codecs.emplace("h264");
|
||||
@@ -42,8 +43,9 @@ GoLiveApi::PostData constructGoLivePost(QString streamKey, const std::optional<u
|
||||
preferences.vod_track_audio = vod_track_enabled;
|
||||
|
||||
obs_video_info ovi;
|
||||
if (obs_get_video_info(&ovi))
|
||||
if (obs_get_video_info(&ovi)) {
|
||||
preferences.composition_gpu_index = ovi.adapter;
|
||||
}
|
||||
|
||||
for (const auto &canvas : canvases) {
|
||||
if (obs_canvas_get_video_info(canvas, &ovi)) {
|
||||
@@ -63,8 +65,9 @@ GoLiveApi::PostData constructGoLivePost(QString streamKey, const std::optional<u
|
||||
preferences.audio_max_buffering_ms = oai2.max_buffering_ms;
|
||||
}
|
||||
|
||||
if (maximum_aggregate_bitrate.has_value())
|
||||
if (maximum_aggregate_bitrate.has_value()) {
|
||||
preferences.maximum_aggregate_bitrate = maximum_aggregate_bitrate.value();
|
||||
}
|
||||
|
||||
if (maximum_video_tracks.has_value()) {
|
||||
/* Cap to maximum supported number of output encoders. */
|
||||
|
||||
@@ -13,13 +13,15 @@ static const char *MAC_DEFAULT_BRANCH = "stable";
|
||||
bool GetBranch(std::string &selectedBranch)
|
||||
{
|
||||
const char *config_branch = config_get_string(App()->GetAppConfig(), "General", "UpdateBranch");
|
||||
if (!config_branch)
|
||||
if (!config_branch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (const UpdateBranch &branch : App()->GetBranches()) {
|
||||
if (branch.name != config_branch)
|
||||
if (branch.name != config_branch) {
|
||||
continue;
|
||||
}
|
||||
/* A branch that is found but disabled will just silently fall back to
|
||||
* the default. But if the branch was removed entirely, the user should
|
||||
* be warned, so leave this false *only* if the branch was removed. */
|
||||
@@ -53,8 +55,9 @@ try {
|
||||
/* ----------------------------------- *
|
||||
* get branches from server */
|
||||
|
||||
if (FetchAndVerifyFile("branches", "obs-studio/updates/branches.json", MAC_BRANCHES_URL, &text))
|
||||
if (FetchAndVerifyFile("branches", "obs-studio/updates/branches.json", MAC_BRANCHES_URL, &text)) {
|
||||
App()->SetBranchData(text);
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* Validate branch selection */
|
||||
|
||||
@@ -46,9 +46,10 @@ int MissingFilesModel::found() const
|
||||
int res = 0;
|
||||
|
||||
for (int i = 0; i < files.length(); i++) {
|
||||
if (files[i].state != Missing && files[i].state != Cleared)
|
||||
if (files[i].state != Missing && files[i].state != Cleared) {
|
||||
res++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -213,8 +214,9 @@ void MissingFilesModel::fileCheckLoop(const QString &path, bool skipPrompt, int
|
||||
os_dir_t *folder = os_opendir(dir.toStdString().c_str());
|
||||
struct os_dirent *ent;
|
||||
while ((ent = os_readdir(folder)) != NULL) {
|
||||
if (!ent->directory || *ent->d_name == '.')
|
||||
if (!ent->directory || *ent->d_name == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString directoryPath = dir + QString(ent->d_name) + "/";
|
||||
fileCheckLoop(directoryPath, true, depthWithoutFileMatch);
|
||||
|
||||
@@ -128,8 +128,9 @@ void MissingFilesPathItemDelegate::handleBrowse(QWidget *container)
|
||||
QLineEdit *text = container->findChild<QLineEdit *>();
|
||||
|
||||
QString currentPath = text->text();
|
||||
if (currentPath.isEmpty() || currentPath.compare(QTStr("MissingFiles.Clear")) == 0)
|
||||
if (currentPath.isEmpty() || currentPath.compare(QTStr("MissingFiles.Clear")) == 0) {
|
||||
currentPath = "";
|
||||
}
|
||||
|
||||
bool isSet = false;
|
||||
|
||||
@@ -146,9 +147,10 @@ void MissingFilesPathItemDelegate::handleBrowse(QWidget *container)
|
||||
isSet = true;
|
||||
}
|
||||
|
||||
if (isSet)
|
||||
if (isSet) {
|
||||
emit commitData(container);
|
||||
}
|
||||
}
|
||||
|
||||
void MissingFilesPathItemDelegate::handleClear(QWidget *container)
|
||||
{
|
||||
|
||||
@@ -50,11 +50,13 @@ static OBSServiceAutoRelease create_service(const GoLiveApi::Config &go_live_con
|
||||
const auto &ingest_endpoints = go_live_config.ingest_endpoints;
|
||||
|
||||
for (auto &endpoint : ingest_endpoints) {
|
||||
if (qstrnicmp("RTMP", endpoint.protocol.c_str(), 4))
|
||||
if (qstrnicmp("RTMP", endpoint.protocol.c_str(), 4)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (use_rtmps.has_value() && *use_rtmps != (qstricmp("RTMPS", endpoint.protocol.c_str()) == 0))
|
||||
if (use_rtmps.has_value() && *use_rtmps != (qstricmp("RTMPS", endpoint.protocol.c_str()) == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
url = endpoint.url_template.c_str();
|
||||
if (endpoint.authentication && !endpoint.authentication->empty()) {
|
||||
@@ -88,9 +90,10 @@ static OBSServiceAutoRelease create_service(const GoLiveApi::Config &go_live_con
|
||||
// not initialize str if cat'ing with a null url
|
||||
if (!dstr_is_empty(str)) {
|
||||
auto found = dstr_find(str, "/{stream_key}");
|
||||
if (found)
|
||||
if (found) {
|
||||
dstr_remove(str, found - str->array, str->len - (found - str->array));
|
||||
}
|
||||
}
|
||||
|
||||
/* The stream key itself may contain query parameters, such as
|
||||
* "bandwidthtest" that need to be carried over. */
|
||||
@@ -102,8 +105,9 @@ static OBSServiceAutoRelease create_service(const GoLiveApi::Config &go_live_con
|
||||
QUrl parsed_url{url};
|
||||
QUrlQuery parsed_query{parsed_url};
|
||||
|
||||
for (const auto &[key, value] : user_key_query.queryItems())
|
||||
for (const auto &[key, value] : user_key_query.queryItems()) {
|
||||
parsed_query.addQueryItem(key, value);
|
||||
}
|
||||
|
||||
if (!go_live_config.meta.config_id.empty()) {
|
||||
parsed_query.addQueryItem("clientConfigId", QString::fromStdString(go_live_config.meta.config_id));
|
||||
@@ -193,12 +197,14 @@ static void adjust_encoder_frame_rate_divisor(const obs_video_info &ovi, obs_enc
|
||||
}
|
||||
media_frames_per_second requested_fps = *encoder_config.framerate;
|
||||
|
||||
if (ovi.fps_num == requested_fps.numerator && ovi.fps_den == requested_fps.denominator)
|
||||
if (ovi.fps_num == requested_fps.numerator && ovi.fps_den == requested_fps.denominator) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto divisor = closest_divisor(ovi, requested_fps);
|
||||
if (divisor <= 1)
|
||||
if (divisor <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "Setting frame rate divisor to %u for encoder %zu", divisor, encoder_index);
|
||||
obs_encoder_set_frame_rate_divisor(video_encoder, divisor);
|
||||
@@ -209,9 +215,10 @@ static bool encoder_available(const char *type)
|
||||
const char *id = nullptr;
|
||||
|
||||
for (size_t idx = 0; obs_enum_encoder_types(idx, &id); idx++) {
|
||||
if (strcmp(id, type) == 0)
|
||||
if (strcmp(id, type) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -381,15 +388,17 @@ void MultitrackVideoOutput::PrepareStreaming(
|
||||
|
||||
std::string canvasNames;
|
||||
for (const auto &canvas : canvases) {
|
||||
if (!canvasNames.empty())
|
||||
if (!canvasNames.empty()) {
|
||||
canvasNames += ", ";
|
||||
}
|
||||
|
||||
canvasNames += obs_canvas_get_name(canvas);
|
||||
}
|
||||
|
||||
DStr vod_track_info_storage;
|
||||
if (vod_track_mixer.has_value())
|
||||
if (vod_track_mixer.has_value()) {
|
||||
dstr_printf(vod_track_info_storage, "Yes (mixer: %zu)", vod_track_mixer.value());
|
||||
}
|
||||
|
||||
blog(LOG_INFO,
|
||||
"Preparing enhanced broadcasting stream for:\n"
|
||||
@@ -464,14 +473,16 @@ void MultitrackVideoOutput::PrepareStreaming(
|
||||
vod_track_mixer, canvases);
|
||||
auto output = std::move(outputs.output);
|
||||
auto recording_output = std::move(outputs.recording_output);
|
||||
if (!output)
|
||||
if (!output) {
|
||||
throw MultitrackVideoError::warning(
|
||||
QTStr("FailedToStartStream.FallbackToDefault").arg(multitrack_video_name));
|
||||
}
|
||||
|
||||
auto multitrack_video_service = create_service(service_config, rtmp_url, stream_key, use_rtmps);
|
||||
if (!multitrack_video_service)
|
||||
if (!multitrack_video_service) {
|
||||
throw MultitrackVideoError::warning(
|
||||
QTStr("FailedToStartStream.FallbackToDefault").arg(multitrack_video_name));
|
||||
}
|
||||
|
||||
obs_output_set_service(output, multitrack_video_service);
|
||||
|
||||
@@ -547,8 +558,9 @@ void MultitrackVideoOutput::StartedStreaming()
|
||||
}
|
||||
}
|
||||
|
||||
if (!dump_output)
|
||||
if (!dump_output) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = obs_output_start(dump_output);
|
||||
blog(LOG_INFO, "MultitrackVideoOutput: starting recording%s", result ? "" : " failed");
|
||||
@@ -561,21 +573,25 @@ void MultitrackVideoOutput::StopStreaming()
|
||||
OBSOutputAutoRelease current_output;
|
||||
{
|
||||
const std::lock_guard current_lock{current_mutex};
|
||||
if (current && current->output_)
|
||||
if (current && current->output_) {
|
||||
current_output = obs_output_get_ref(current->output_);
|
||||
}
|
||||
if (current_output)
|
||||
}
|
||||
if (current_output) {
|
||||
obs_output_stop(current_output);
|
||||
}
|
||||
|
||||
OBSOutputAutoRelease dump_output;
|
||||
{
|
||||
const std::lock_guard current_stream_dump_lock{current_stream_dump_mutex};
|
||||
if (current_stream_dump && current_stream_dump->output_)
|
||||
if (current_stream_dump && current_stream_dump->output_) {
|
||||
dump_output = obs_output_get_ref(current_stream_dump->output_);
|
||||
}
|
||||
if (dump_output)
|
||||
}
|
||||
if (dump_output) {
|
||||
obs_output_stop(dump_output);
|
||||
}
|
||||
}
|
||||
|
||||
static bool create_video_encoders(const GoLiveApi::Config &go_live_config,
|
||||
std::shared_ptr<obs_encoder_group_t> &video_encoder_group, obs_output_t *output,
|
||||
@@ -589,8 +605,9 @@ static bool create_video_encoders(const GoLiveApi::Config &go_live_config,
|
||||
}
|
||||
|
||||
std::shared_ptr<obs_encoder_group_t> encoder_group(obs_encoder_group_create(), obs_encoder_group_destroy);
|
||||
if (!encoder_group)
|
||||
if (!encoder_group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto max_canvas_idx = canvases.size() - 1;
|
||||
|
||||
@@ -603,15 +620,18 @@ static bool create_video_encoders(const GoLiveApi::Config &go_live_config,
|
||||
|
||||
auto &canvas = canvases[config.canvas_index];
|
||||
auto encoder = create_video_encoder(video_encoder_name_buffer, i, config, canvas);
|
||||
if (!encoder)
|
||||
if (!encoder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obs_encoder_set_group(encoder, encoder_group.get()))
|
||||
if (!obs_encoder_set_group(encoder, encoder_group.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
obs_output_set_video_encoder2(output, encoder, i);
|
||||
if (recording_output)
|
||||
if (recording_output) {
|
||||
obs_output_set_video_encoder2(recording_output, encoder, i);
|
||||
}
|
||||
|
||||
auto &data = go_live_config.encoder_configurations[i].bitrate_interpolation_points;
|
||||
if (data.has_value()) {
|
||||
@@ -633,16 +653,18 @@ static void create_audio_encoders(const GoLiveApi::Config &go_live_config,
|
||||
{
|
||||
speaker_layout speakers = SPEAKERS_UNKNOWN;
|
||||
obs_audio_info oai = {};
|
||||
if (obs_get_audio_info(&oai))
|
||||
if (obs_get_audio_info(&oai)) {
|
||||
speakers = oai.speakers;
|
||||
}
|
||||
|
||||
current_layout = speakers;
|
||||
|
||||
auto sanitize_audio_channels = [&](obs_encoder_t *encoder, uint32_t channels) {
|
||||
speaker_layout target_speakers = SPEAKERS_UNKNOWN;
|
||||
for (size_t i = 0; i <= (size_t)SPEAKERS_7POINT1; i++) {
|
||||
if (get_audio_channels((speaker_layout)i) != channels)
|
||||
if (get_audio_channels((speaker_layout)i) != channels) {
|
||||
continue;
|
||||
}
|
||||
|
||||
target_speakers = (speaker_layout)i;
|
||||
break;
|
||||
@@ -656,12 +678,14 @@ static void create_audio_encoders(const GoLiveApi::Config &go_live_config,
|
||||
return;
|
||||
}
|
||||
if (speakers != SPEAKERS_UNKNOWN &&
|
||||
(channels > get_audio_channels(speakers) || speakers == target_speakers))
|
||||
(channels > get_audio_channels(speakers) || speakers == target_speakers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = std::find(std::begin(speaker_layouts), std::end(speaker_layouts), target_speakers);
|
||||
if (it == std::end(speaker_layouts))
|
||||
if (it == std::end(speaker_layouts)) {
|
||||
speaker_layouts.push_back(target_speakers);
|
||||
}
|
||||
};
|
||||
|
||||
using encoder_configs_type = decltype(go_live_config.audio_configurations.live);
|
||||
@@ -692,8 +716,9 @@ static void create_audio_encoders(const GoLiveApi::Config &go_live_config,
|
||||
sanitize_audio_channels(audio_encoder, configs[i].channels);
|
||||
|
||||
obs_output_set_audio_encoder(output, audio_encoder, output_encoder_index);
|
||||
if (recording_output)
|
||||
if (recording_output) {
|
||||
obs_output_set_audio_encoder(recording_output, audio_encoder, output_encoder_index);
|
||||
}
|
||||
output_encoder_index += 1;
|
||||
audio_encoders.emplace_back(std::move(audio_encoder));
|
||||
}
|
||||
@@ -701,8 +726,9 @@ static void create_audio_encoders(const GoLiveApi::Config &go_live_config,
|
||||
|
||||
create_encoders("multitrack video live audio", go_live_config.audio_configurations.live, main_audio_mixer);
|
||||
|
||||
if (!vod_track_mixer.has_value())
|
||||
if (!vod_track_mixer.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we already check for empty inside of `create_encoders`
|
||||
encoder_configs_type empty = {};
|
||||
@@ -738,8 +764,9 @@ static const char *speaker_layout_to_string(speaker_layout layout)
|
||||
static void handle_speaker_layout_issues(QWidget *parent, const QString &multitrack_video_name,
|
||||
const std::vector<speaker_layout> &requested_layouts, speaker_layout layout)
|
||||
{
|
||||
if (requested_layouts.empty())
|
||||
if (requested_layouts.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString message;
|
||||
if (requested_layouts.size() == 1) {
|
||||
@@ -783,13 +810,15 @@ static OBSOutputs SetupOBSOutput(QWidget *parent, const QString &multitrack_vide
|
||||
{
|
||||
auto output = create_output();
|
||||
OBSOutputAutoRelease recording_output;
|
||||
if (dump_stream_to_file_config)
|
||||
if (dump_stream_to_file_config) {
|
||||
recording_output = create_recording_output(dump_stream_to_file_config);
|
||||
}
|
||||
|
||||
json bitrate_interpolation_array = json::array();
|
||||
if (!create_video_encoders(go_live_config, video_encoder_group, output, recording_output,
|
||||
bitrate_interpolation_array, canvases))
|
||||
bitrate_interpolation_array, canvases)) {
|
||||
return {nullptr, nullptr};
|
||||
}
|
||||
|
||||
OBSDataAutoRelease settings = obs_output_get_settings(output);
|
||||
// Only set interpolation_table_data if every encoder has interpolation points. Partial data would
|
||||
@@ -845,8 +874,9 @@ std::optional<MultitrackVideoOutput::OBSOutputObjects> MultitrackVideoOutput::ta
|
||||
void MultitrackVideoOutput::ReleaseOnMainThread(std::optional<OBSOutputObjects> objects)
|
||||
{
|
||||
|
||||
if (!objects.has_value())
|
||||
if (!objects.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
QApplication::instance()->thread(), [objects = std::move(objects)] {}, Qt::QueuedConnection);
|
||||
@@ -866,11 +896,13 @@ void StreamStopHandler(void *arg, calldata_t *data)
|
||||
OBSOutputAutoRelease stream_dump_output;
|
||||
{
|
||||
const std::lock_guard<std::mutex> current_stream_dump_lock{self->current_stream_dump_mutex};
|
||||
if (self->current_stream_dump && self->current_stream_dump->output_)
|
||||
if (self->current_stream_dump && self->current_stream_dump->output_) {
|
||||
stream_dump_output = obs_output_get_ref(self->current_stream_dump->output_);
|
||||
}
|
||||
if (stream_dump_output)
|
||||
}
|
||||
if (stream_dump_output) {
|
||||
obs_output_stop(stream_dump_output);
|
||||
}
|
||||
|
||||
/* Unregister the BPM (Broadcast Performance Metrics) callback and destroy the allocated metrics data. */
|
||||
obs_output_remove_packet_callback(static_cast<obs_output_t *>(calldata_ptr(data, "output")), bpm_inject, NULL);
|
||||
|
||||
@@ -30,8 +30,9 @@ Canvas::Canvas(Canvas &&other) noexcept
|
||||
|
||||
Canvas::~Canvas() noexcept
|
||||
{
|
||||
if (!canvas)
|
||||
if (!canvas) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_canvas_remove(canvas);
|
||||
obs_canvas_release(canvas);
|
||||
@@ -47,10 +48,12 @@ Canvas &Canvas::operator=(Canvas &&other) noexcept
|
||||
|
||||
std::optional<OBSDataAutoRelease> Canvas::Save() const
|
||||
{
|
||||
if (!canvas)
|
||||
if (!canvas) {
|
||||
return std::nullopt;
|
||||
if (obs_data_t *saved = obs_save_canvas(canvas))
|
||||
}
|
||||
if (obs_data_t *saved = obs_save_canvas(canvas)) {
|
||||
return saved;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -70,8 +73,9 @@ std::vector<Canvas> Canvas::LoadCanvases(obs_data_array_t *canvases)
|
||||
{
|
||||
auto cb = [](obs_data_t *data, void *param) -> void {
|
||||
auto vec = static_cast<std::vector<Canvas> *>(param);
|
||||
if (auto canvas = Canvas::Load(data))
|
||||
if (auto canvas = Canvas::Load(data)) {
|
||||
vec->emplace_back(std::move(*canvas));
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Canvas> ret;
|
||||
@@ -86,8 +90,9 @@ OBSDataArrayAutoRelease Canvas::SaveCanvases(const std::vector<Canvas> &canvases
|
||||
|
||||
for (auto &canvas : canvases) {
|
||||
auto canvas_data = canvas.Save();
|
||||
if (!canvas_data)
|
||||
if (!canvas_data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_obj(data, "info", *canvas_data);
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
int OBSProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
|
||||
QStyleHintReturn *returnData) const
|
||||
{
|
||||
if (hint == SH_ComboBox_AllowWheelScrolling)
|
||||
if (hint == SH_ComboBox_AllowWheelScrolling) {
|
||||
return 0;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
if (hint == SH_ComboBox_UseNativePopup)
|
||||
if (hint == SH_ComboBox_UseNativePopup) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||
@@ -18,8 +20,9 @@ int OBSInvisibleCursorProxyStyle::pixelMetric(PixelMetric metric, const QStyleOp
|
||||
const QWidget *widget) const
|
||||
{
|
||||
|
||||
if (metric == PM_TextCursorWidth)
|
||||
if (metric == PM_TextCursorWidth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return QProxyStyle::pixelMetric(metric, option, widget);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ QString OBSTranslator::translate(const char *, const char *sourceText, const cha
|
||||
const char *out = nullptr;
|
||||
QString str(sourceText);
|
||||
str.replace(" ", "");
|
||||
if (!App()->TranslateString(QT_TO_UTF8(str), &out))
|
||||
if (!App()->TranslateString(QT_TO_UTF8(str), &out)) {
|
||||
return QString(sourceText);
|
||||
}
|
||||
|
||||
return QT_UTF8(out);
|
||||
}
|
||||
|
||||
@@ -25,13 +25,15 @@ static inline QString MakeQuickTransitionText(QuickTransition *qt)
|
||||
{
|
||||
QString name;
|
||||
|
||||
if (!qt->fadeToBlack)
|
||||
if (!qt->fadeToBlack) {
|
||||
name = QT_UTF8(obs_source_get_name(qt->source));
|
||||
else
|
||||
} else {
|
||||
name = QTStr("FadeToBlack");
|
||||
}
|
||||
|
||||
if (!obs_transition_fixed(qt->source))
|
||||
if (!obs_transition_fixed(qt->source)) {
|
||||
name += QString(" (%1ms)").arg(QString::number(qt->duration));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,9 @@ using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
|
||||
static size_t string_write(char *ptr, size_t size, size_t nmemb, string &str)
|
||||
{
|
||||
size_t total = size * nmemb;
|
||||
if (total)
|
||||
if (total) {
|
||||
str.append(ptr, total);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
@@ -66,8 +67,9 @@ void RemoteTextThread::run()
|
||||
header = curl_slist_append(header, contentTypeString.c_str());
|
||||
}
|
||||
|
||||
for (std::string &h : extraHeaders)
|
||||
for (std::string &h : extraHeaders) {
|
||||
header = curl_slist_append(header, h.c_str());
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ACCEPT_ENCODING, "");
|
||||
@@ -78,8 +80,9 @@ void RemoteTextThread::run()
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
|
||||
curl_obs_set_revoke_setting(curl.get());
|
||||
|
||||
if (timeoutSec)
|
||||
if (timeoutSec) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, timeoutSec);
|
||||
}
|
||||
|
||||
if (!postData.empty()) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, postData.c_str());
|
||||
@@ -103,13 +106,16 @@ static size_t header_write(char *ptr, size_t size, size_t nmemb, vector<string>
|
||||
string str;
|
||||
|
||||
size_t total = size * nmemb;
|
||||
if (total)
|
||||
if (total) {
|
||||
str.append(ptr, total);
|
||||
}
|
||||
|
||||
if (str.back() == '\n')
|
||||
if (str.back() == '\n') {
|
||||
str.resize(str.size() - 1);
|
||||
if (str.back() == '\r')
|
||||
}
|
||||
if (str.back() == '\r') {
|
||||
str.resize(str.size() - 1);
|
||||
}
|
||||
|
||||
list.push_back(std::move(str));
|
||||
return total;
|
||||
@@ -144,15 +150,17 @@ bool GetRemoteFile(const char *url, std::string &str, std::string &error, long *
|
||||
header = curl_slist_append(header, contentTypeString.c_str());
|
||||
}
|
||||
|
||||
for (std::string &h : extraHeaders)
|
||||
for (std::string &h : extraHeaders) {
|
||||
header = curl_slist_append(header, h.c_str());
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, header);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, error_in);
|
||||
if (fail_on_error)
|
||||
if (fail_on_error) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
|
||||
}
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
|
||||
curl_obs_set_revoke_setting(curl.get());
|
||||
@@ -162,20 +170,23 @@ bool GetRemoteFile(const char *url, std::string &str, std::string &error, long *
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA, &header_in_list);
|
||||
}
|
||||
|
||||
if (timeoutSec)
|
||||
if (timeoutSec) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, timeoutSec);
|
||||
}
|
||||
|
||||
if (!request_type.empty()) {
|
||||
if (request_type != "GET")
|
||||
if (request_type != "GET") {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_CUSTOMREQUEST, request_type.c_str());
|
||||
}
|
||||
|
||||
// Special case of "POST"
|
||||
if (request_type == "POST") {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POST, 1);
|
||||
if (!postData)
|
||||
if (!postData) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, "{}");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (postData) {
|
||||
if (postDataSize > 0) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDSIZE, (long)postDataSize);
|
||||
@@ -184,8 +195,9 @@ bool GetRemoteFile(const char *url, std::string &str, std::string &error, long *
|
||||
}
|
||||
|
||||
code = curl_easy_perform(curl.get());
|
||||
if (responseCode)
|
||||
if (responseCode) {
|
||||
curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, responseCode);
|
||||
}
|
||||
|
||||
if (code != CURLE_OK) {
|
||||
error = strlen(error_in) ? error_in : curl_easy_strerror(code);
|
||||
|
||||
@@ -125,10 +125,12 @@ void RemuxEntryPathItemDelegate::setModelData(QWidget *editor, QAbstractItemMode
|
||||
if (pathListProp.isValid()) {
|
||||
QStringList list = editor->property(PATH_LIST_PROP).toStringList();
|
||||
if (isOutput) {
|
||||
if (list.size() > 0)
|
||||
if (list.size() > 0) {
|
||||
model->setData(index, list);
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
model->setData(index, list, RemuxEntryRole::NewPathsToProcessRole);
|
||||
}
|
||||
} else {
|
||||
QLineEdit *lineEdit = editor->findChild<QLineEdit *>();
|
||||
model->setData(index, lineEdit->text());
|
||||
@@ -165,8 +167,9 @@ void RemuxEntryPathItemDelegate::handleBrowse(QWidget *container)
|
||||
QLineEdit *text = container->findChild<QLineEdit *>();
|
||||
|
||||
QString currentPath = text->text();
|
||||
if (currentPath.isEmpty())
|
||||
if (currentPath.isEmpty()) {
|
||||
currentPath = defaultPath;
|
||||
}
|
||||
|
||||
bool isSet = false;
|
||||
if (isOutput) {
|
||||
@@ -190,9 +193,10 @@ void RemuxEntryPathItemDelegate::handleBrowse(QWidget *container)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (isSet)
|
||||
if (isSet) {
|
||||
emit commitData(container);
|
||||
}
|
||||
}
|
||||
|
||||
void RemuxEntryPathItemDelegate::handleClear(QWidget *container)
|
||||
{
|
||||
|
||||
@@ -218,10 +218,11 @@ void RemuxQueueModel::checkInputPath(int row)
|
||||
} else {
|
||||
entry.sourcePath = QDir::toNativeSeparators(entry.sourcePath);
|
||||
QFileInfo fileInfo(entry.sourcePath);
|
||||
if (fileInfo.exists())
|
||||
if (fileInfo.exists()) {
|
||||
entry.state = RemuxEntryState::Ready;
|
||||
else
|
||||
} else {
|
||||
entry.state = RemuxEntryState::InvalidPath;
|
||||
}
|
||||
|
||||
QString newExt = ".mp4";
|
||||
QString suffix = fileInfo.suffix();
|
||||
@@ -230,13 +231,15 @@ void RemuxQueueModel::checkInputPath(int row)
|
||||
newExt = ".remuxed." + suffix;
|
||||
}
|
||||
|
||||
if (entry.state == RemuxEntryState::Ready)
|
||||
if (entry.state == RemuxEntryState::Ready) {
|
||||
entry.targetPath = QDir::toNativeSeparators(fileInfo.path() + QDir::separator() +
|
||||
fileInfo.completeBaseName() + newExt);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.state == RemuxEntryState::Ready && isProcessing)
|
||||
if (entry.state == RemuxEntryState::Ready && isProcessing) {
|
||||
entry.state = RemuxEntryState::Pending;
|
||||
}
|
||||
|
||||
emit dataChanged(index(row, 0), index(row, RemuxEntryColumn::Count));
|
||||
}
|
||||
@@ -296,20 +299,23 @@ void RemuxQueueModel::clearFinished()
|
||||
bool RemuxQueueModel::canClearFinished() const
|
||||
{
|
||||
bool canClearFinished = false;
|
||||
for (const RemuxQueueEntry &entry : queue)
|
||||
for (const RemuxQueueEntry &entry : queue) {
|
||||
if (entry.state == RemuxEntryState::Complete) {
|
||||
canClearFinished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return canClearFinished;
|
||||
}
|
||||
|
||||
void RemuxQueueModel::beginProcessing()
|
||||
{
|
||||
for (RemuxQueueEntry &entry : queue)
|
||||
if (entry.state == RemuxEntryState::Ready)
|
||||
for (RemuxQueueEntry &entry : queue) {
|
||||
if (entry.state == RemuxEntryState::Ready) {
|
||||
entry.state = RemuxEntryState::Pending;
|
||||
}
|
||||
}
|
||||
|
||||
// Signal that the insertion point no longer exists.
|
||||
beginRemoveRows(QModelIndex(), queue.length(), queue.length());
|
||||
@@ -366,10 +372,11 @@ void RemuxQueueModel::finishEntry(bool success)
|
||||
for (int row = 0; row < queue.length(); row++) {
|
||||
RemuxQueueEntry &entry = queue[row];
|
||||
if (entry.state == RemuxEntryState::InProgress) {
|
||||
if (success)
|
||||
if (success) {
|
||||
entry.state = RemuxEntryState::Complete;
|
||||
else
|
||||
} else {
|
||||
entry.state = RemuxEntryState::Error;
|
||||
}
|
||||
|
||||
QModelIndex index = this->index(row, RemuxEntryColumn::State);
|
||||
emit dataChanged(index, index);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user