frontend: Split main application implementation into single files

This commit is contained in:
PatTheMav 2024-12-11 19:03:30 +01:00
parent bcc6880183
commit 2be464a21f
No known key found for this signature in database
11 changed files with 940 additions and 7095 deletions

File diff suppressed because it is too large Load Diff

View File

@ -17,63 +17,30 @@
#pragma once
#include <QApplication>
#include <QTranslator>
#include <QPointer>
#include <QFileSystemWatcher>
#include <utility/OBSTheme.hpp>
#include <widgets/OBSMainWindow.hpp>
#ifndef _WIN32
#include <QSocketNotifier>
#else
#include <QSessionManager>
#endif
#include <obs.hpp>
#include <util/lexer.h>
#include <util/profiler.h>
#include <util/util.hpp>
#include <util/platform.h>
#include <obs-frontend-api.h>
#include <util/platform.h>
#include <util/profiler.hpp>
#include <util/util.hpp>
#include <QApplication>
#include <QPalette>
#include <QPointer>
#include <deque>
#include <functional>
#include <string>
#include <memory>
#include <vector>
#include <deque>
#include <filesystem>
#include "window-main.hpp"
#include "obs-app-theming.hpp"
std::string CurrentTimeString();
std::string CurrentDateTimeString();
std::string GenerateTimeDateFilename(const char *extension, bool noSpace = false);
std::string GenerateSpecifiedFilename(const char *extension, bool noSpace, const char *format);
std::string GetFormatString(const char *format, const char *prefix, const char *suffix);
std::string GetFormatExt(const char *container);
std::string GetOutputFilename(const char *path, const char *container, bool noSpace, bool overwrite,
const char *format);
QObject *CreateShortcutFilter();
struct BaseLexer {
lexer lex;
public:
inline BaseLexer() { lexer_init(&lex); }
inline ~BaseLexer() { lexer_free(&lex); }
operator lexer *() { return &lex; }
};
class OBSTranslator : public QTranslator {
Q_OBJECT
public:
virtual bool isEmpty() const override { return false; }
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation,
int n) const override;
};
typedef std::function<void()> VoidFunc;
Q_DECLARE_METATYPE(VoidFunc)
class QFileSystemWatcher;
class QSocketNotifier;
struct UpdateBranch {
QString name;
QString display_name;
@ -233,9 +200,6 @@ signals:
int GetAppConfigPath(char *path, size_t size, const char *name);
char *GetAppConfigPathPtr(const char *name);
int GetProgramDataPath(char *path, size_t size, const char *name);
char *GetProgramDataPathPtr(const char *name);
inline OBSApp *App()
{
return static_cast<OBSApp *>(qApp);
@ -251,30 +215,23 @@ inline QString QTStr(const char *lookupVal)
return QString::fromUtf8(Str(lookupVal));
}
int GetProgramDataPath(char *path, size_t size, const char *name);
char *GetProgramDataPathPtr(const char *name);
bool GetFileSafeName(const char *name, std::string &file);
bool GetClosestUnusedFileName(std::string &path, const char *extension);
bool GetUnusedSceneCollectionFile(std::string &name, std::string &file);
bool WindowPositionValid(QRect rect);
extern bool portable_mode;
extern bool steam;
extern bool safe_mode;
extern bool disable_3p_plugins;
extern bool opt_start_streaming;
extern bool opt_start_recording;
extern bool opt_start_replaybuffer;
extern bool opt_start_virtualcam;
extern bool opt_minimize_tray;
extern bool opt_studio_mode;
extern bool opt_allow_opengl;
extern bool opt_always_on_top;
extern std::string opt_starting_scene;
extern bool restart;
extern bool restart_safe;
#ifdef _WIN32
extern "C" void install_dll_blocklist_hook(void);
extern "C" void log_blocked_dlls(void);
#endif
std::string CurrentDateTimeString();
std::string GetFormatString(const char *format, const char *prefix, const char *suffix);
std::string GenerateTimeDateFilename(const char *extension, bool noSpace = false);
std::string GetFormatExt(const char *container);
std::string GetOutputFilename(const char *path, const char *container, bool noSpace, bool overwrite,
const char *format);
QObject *CreateShortcutFilter();

View File

@ -15,25 +15,23 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#include <cinttypes>
#include "OBSApp.hpp"
#include <utility/OBSProxyStyle.hpp>
#include <utility/OBSThemeVariable.hpp>
#include <utility/platform.hpp>
#include <qt-wrappers.hpp>
#include <ui-config.h>
#include <util/cf-parser.h>
#include <QDir>
#include <QFile>
#include <QTimer>
#include <QMetaEnum>
#include <QDirIterator>
#include <QGuiApplication>
#include <QFile>
#include <QFileSystemWatcher>
#include <QMetaEnum>
#include <QRandomGenerator>
#include "qt-wrappers.hpp"
#include "obs-app.hpp"
#include "obs-app-theming.hpp"
#include "obs-proxy-style.hpp"
#include "platform.hpp"
#include "ui-config.h"
#include <QTimer>
using namespace std;

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +1,28 @@
#include <obs-frontend-internal.hpp>
#include <qt-wrappers.hpp>
#include "obs-app.hpp"
#include "window-basic-main.hpp"
#include "window-basic-main-outputs.hpp"
/******************************************************************************
Copyright (C) 2024 by Patrick Heyer <opensource@patrickheyer.com>
#include <functional>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
#pragma once
#include <obs-frontend-internal.hpp>
class OBSBasic;
using namespace std;
Q_DECLARE_METATYPE(OBSScene);
Q_DECLARE_METATYPE(OBSSource);
template<typename T> static T GetOBSRef(QListWidgetItem *item)
{
return item->data(static_cast<int>(QtDataRole::OBSRef)).value<T>();
}
extern volatile bool streaming_active;
extern volatile bool recording_active;
extern volatile bool recording_paused;
extern volatile bool replaybuf_active;
extern volatile bool virtualcam_active;
/* ------------------------------------------------------------------------- */
template<typename T> struct OBSStudioCallback {
T callback;
void *private_data;
@ -31,18 +30,6 @@ template<typename T> struct OBSStudioCallback {
inline OBSStudioCallback(T cb, void *p) : callback(cb), private_data(p) {}
};
template<typename T>
inline size_t GetCallbackIdx(vector<OBSStudioCallback<T>> &callbacks, T callback, void *private_data)
{
for (size_t i = 0; i < callbacks.size(); i++) {
OBSStudioCallback<T> curCB = callbacks[i];
if (curCB.callback == callback && curCB.private_data == private_data)
return i;
}
return (size_t)-1;
}
struct OBSStudioAPI : obs_frontend_callbacks {
OBSBasic *main;
vector<OBSStudioCallback<obs_frontend_event_cb>> callbacks;
@ -51,586 +38,199 @@ struct OBSStudioAPI : obs_frontend_callbacks {
inline OBSStudioAPI(OBSBasic *main_) : main(main_) {}
void *obs_frontend_get_main_window(void) override { return (void *)main; }
void *obs_frontend_get_main_window_handle(void) override { return (void *)main->winId(); }
void *obs_frontend_get_system_tray(void) override { return (void *)main->trayIcon.data(); }
void obs_frontend_get_scenes(struct obs_frontend_source_list *sources) override
{
for (int i = 0; i < main->ui->scenes->count(); i++) {
QListWidgetItem *item = main->ui->scenes->item(i);
OBSScene scene = GetOBSRef<OBSScene>(item);
obs_source_t *source = obs_scene_get_source(scene);
if (obs_source_get_ref(source) != nullptr)
da_push_back(sources->sources, &source);
}
}
obs_source_t *obs_frontend_get_current_scene(void) override
{
if (main->IsPreviewProgramMode()) {
return obs_weak_source_get_source(main->programScene);
} else {
OBSSource source = main->GetCurrentSceneSource();
return obs_source_get_ref(source);
}
}
void obs_frontend_set_current_scene(obs_source_t *scene) override
{
if (main->IsPreviewProgramMode()) {
QMetaObject::invokeMethod(main, "TransitionToScene", WaitConnection(),
Q_ARG(OBSSource, OBSSource(scene)));
} else {
QMetaObject::invokeMethod(main, "SetCurrentScene", WaitConnection(),
Q_ARG(OBSSource, OBSSource(scene)), Q_ARG(bool, false));
}
}
void obs_frontend_get_transitions(struct obs_frontend_source_list *sources) override
{
for (int i = 0; i < main->ui->transitions->count(); i++) {
OBSSource tr = main->ui->transitions->itemData(i).value<OBSSource>();
if (!tr)
continue;
if (obs_source_get_ref(tr) != nullptr)
da_push_back(sources->sources, &tr);
}
}
obs_source_t *obs_frontend_get_current_transition(void) override
{
OBSSource tr = main->GetCurrentTransition();
return obs_source_get_ref(tr);
}
void obs_frontend_set_current_transition(obs_source_t *transition) override
{
QMetaObject::invokeMethod(main, "SetTransition", Q_ARG(OBSSource, OBSSource(transition)));
}
int obs_frontend_get_transition_duration(void) override { return main->ui->transitionDuration->value(); }
void obs_frontend_set_transition_duration(int duration) override
{
QMetaObject::invokeMethod(main->ui->transitionDuration, "setValue", Q_ARG(int, duration));
}
void obs_frontend_release_tbar(void) override { QMetaObject::invokeMethod(main, "TBarReleased"); }
void obs_frontend_set_tbar_position(int position) override
{
QMetaObject::invokeMethod(main, "TBarChanged", Q_ARG(int, position));
}
int obs_frontend_get_tbar_position(void) override { return main->tBar->value(); }
void obs_frontend_get_scene_collections(std::vector<std::string> &strings) override
{
for (auto &[collectionName, collection] : main->GetSceneCollectionCache()) {
strings.emplace_back(collectionName);
}
}
char *obs_frontend_get_current_scene_collection(void) override
{
const OBSSceneCollection &currentCollection = main->GetCurrentSceneCollection();
return bstrdup(currentCollection.name.c_str());
}
void obs_frontend_set_current_scene_collection(const char *collection) override
{
QList<QAction *> menuActions = main->ui->sceneCollectionMenu->actions();
QString qstrCollection = QT_UTF8(collection);
for (int i = 0; i < menuActions.count(); i++) {
QAction *action = menuActions[i];
QVariant v = action->property("file_name");
if (v.typeName() != nullptr) {
if (action->text() == qstrCollection) {
action->trigger();
break;
}
}
}
}
bool obs_frontend_add_scene_collection(const char *name) override
{
bool success = false;
QMetaObject::invokeMethod(main, "CreateNewSceneCollection", WaitConnection(),
Q_RETURN_ARG(bool, success), Q_ARG(QString, QT_UTF8(name)));
return success;
}
void obs_frontend_get_profiles(std::vector<std::string> &strings) override
{
const OBSProfileCache &profiles = main->GetProfileCache();
for (auto &[profileName, profile] : profiles) {
strings.emplace_back(profileName);
}
}
char *obs_frontend_get_current_profile(void) override
{
const OBSProfile &profile = main->GetCurrentProfile();
return bstrdup(profile.name.c_str());
}
char *obs_frontend_get_current_profile_path(void) override
{
const OBSProfile &profile = main->GetCurrentProfile();
return bstrdup(profile.path.u8string().c_str());
}
void obs_frontend_set_current_profile(const char *profile) override
{
QList<QAction *> menuActions = main->ui->profileMenu->actions();
QString qstrProfile = QT_UTF8(profile);
for (int i = 0; i < menuActions.count(); i++) {
QAction *action = menuActions[i];
QVariant v = action->property("file_name");
if (v.typeName() != nullptr) {
if (action->text() == qstrProfile) {
action->trigger();
break;
}
}
}
}
void obs_frontend_create_profile(const char *name) override
{
QMetaObject::invokeMethod(main, "CreateNewProfile", Q_ARG(QString, name));
}
void obs_frontend_duplicate_profile(const char *name) override
{
QMetaObject::invokeMethod(main, "CreateDuplicateProfile", Q_ARG(QString, name));
}
void obs_frontend_delete_profile(const char *profile) override
{
QMetaObject::invokeMethod(main, "DeleteProfile", Q_ARG(QString, profile));
}
void obs_frontend_streaming_start(void) override { QMetaObject::invokeMethod(main, "StartStreaming"); }
void obs_frontend_streaming_stop(void) override { QMetaObject::invokeMethod(main, "StopStreaming"); }
bool obs_frontend_streaming_active(void) override { return os_atomic_load_bool(&streaming_active); }
void obs_frontend_recording_start(void) override { QMetaObject::invokeMethod(main, "StartRecording"); }
void obs_frontend_recording_stop(void) override { QMetaObject::invokeMethod(main, "StopRecording"); }
bool obs_frontend_recording_active(void) override { return os_atomic_load_bool(&recording_active); }
void obs_frontend_recording_pause(bool pause) override
{
QMetaObject::invokeMethod(main, pause ? "PauseRecording" : "UnpauseRecording");
}
bool obs_frontend_recording_paused(void) override { return os_atomic_load_bool(&recording_paused); }
bool obs_frontend_recording_split_file(void) override
{
if (os_atomic_load_bool(&recording_active) && !os_atomic_load_bool(&recording_paused)) {
proc_handler_t *ph = obs_output_get_proc_handler(main->outputHandler->fileOutput);
uint8_t stack[128];
calldata cd;
calldata_init_fixed(&cd, stack, sizeof(stack));
proc_handler_call(ph, "split_file", &cd);
bool result = calldata_bool(&cd, "split_file_enabled");
return result;
} else {
return false;
}
}
bool obs_frontend_recording_add_chapter(const char *name) override
{
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);
calldata cd;
calldata_init(&cd);
calldata_set_string(&cd, "chapter_name", name);
bool result = proc_handler_call(ph, "add_chapter", &cd);
calldata_free(&cd);
return result;
}
void obs_frontend_replay_buffer_start(void) override { QMetaObject::invokeMethod(main, "StartReplayBuffer"); }
void obs_frontend_replay_buffer_save(void) override { QMetaObject::invokeMethod(main, "ReplayBufferSave"); }
void obs_frontend_replay_buffer_stop(void) override { QMetaObject::invokeMethod(main, "StopReplayBuffer"); }
bool obs_frontend_replay_buffer_active(void) override { return os_atomic_load_bool(&replaybuf_active); }
void *obs_frontend_add_tools_menu_qaction(const char *name) override
{
main->ui->menuTools->setEnabled(true);
return (void *)main->ui->menuTools->addAction(QT_UTF8(name));
}
void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback, void *private_data) override
{
main->ui->menuTools->setEnabled(true);
auto func = [private_data, callback]() {
callback(private_data);
};
QAction *action = main->ui->menuTools->addAction(QT_UTF8(name));
QObject::connect(action, &QAction::triggered, func);
}
void *obs_frontend_add_dock(void *dock) override
{
QDockWidget *d = reinterpret_cast<QDockWidget *>(dock);
QString name = d->objectName();
if (name.isEmpty() || main->IsDockObjectNameUsed(name)) {
blog(LOG_WARNING, "The object name of the added dock is empty or already used,"
" a temporary one will be set to avoid conflicts");
char *uuid = os_generate_uuid();
name = QT_UTF8(uuid);
bfree(uuid);
name.append("_oldExtraDock");
d->setObjectName(name);
}
return (void *)main->AddDockWidget(d);
}
bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget) override
{
if (main->IsDockObjectNameUsed(QT_UTF8(id))) {
blog(LOG_WARNING,
"Dock id '%s' already used! "
"Duplicate library?",
id);
return false;
}
OBSDock *dock = new OBSDock(main);
dock->setWidget((QWidget *)widget);
dock->setWindowTitle(QT_UTF8(title));
dock->setObjectName(QT_UTF8(id));
main->AddDockWidget(dock, Qt::RightDockWidgetArea);
dock->setVisible(false);
dock->setFloating(true);
return true;
}
void obs_frontend_remove_dock(const char *id) override { main->RemoveDockWidget(QT_UTF8(id)); }
bool obs_frontend_add_custom_qdock(const char *id, void *dock) override
{
if (main->IsDockObjectNameUsed(QT_UTF8(id))) {
blog(LOG_WARNING,
"Dock id '%s' already used! "
"Duplicate library?",
id);
return false;
}
QDockWidget *d = reinterpret_cast<QDockWidget *>(dock);
d->setObjectName(QT_UTF8(id));
main->AddCustomDockWidget(d);
return true;
}
void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data) override
{
size_t idx = GetCallbackIdx(callbacks, callback, private_data);
if (idx == (size_t)-1)
callbacks.emplace_back(callback, private_data);
}
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data) override
{
size_t idx = GetCallbackIdx(callbacks, callback, private_data);
if (idx == (size_t)-1)
return;
callbacks.erase(callbacks.begin() + idx);
}
obs_output_t *obs_frontend_get_streaming_output(void) override
{
auto multitrackVideo = main->outputHandler->multitrackVideo.get();
auto mtvOutput = multitrackVideo ? obs_output_get_ref(multitrackVideo->StreamingOutput()) : nullptr;
if (mtvOutput)
return mtvOutput;
OBSOutput output = main->outputHandler->streamOutput.Get();
return obs_output_get_ref(output);
}
obs_output_t *obs_frontend_get_recording_output(void) override
{
OBSOutput out = main->outputHandler->fileOutput.Get();
return obs_output_get_ref(out);
}
obs_output_t *obs_frontend_get_replay_buffer_output(void) override
{
OBSOutput out = main->outputHandler->replayBuffer.Get();
return obs_output_get_ref(out);
}
config_t *obs_frontend_get_profile_config(void) override { return main->activeConfiguration; }
config_t *obs_frontend_get_global_config(void) override
{
blog(LOG_WARNING,
"DEPRECATION: obs_frontend_get_global_config is deprecated. Read from global or user configuration explicitly instead.");
return App()->GetAppConfig();
}
config_t *obs_frontend_get_app_config(void) override { return App()->GetAppConfig(); }
config_t *obs_frontend_get_user_config(void) override { return App()->GetUserConfig(); }
void obs_frontend_open_projector(const char *type, int monitor, const char *geometry, const char *name) override
{
SavedProjectorInfo proj = {
ProjectorType::Preview,
monitor,
geometry ? geometry : "",
name ? name : "",
};
if (type) {
if (astrcmpi(type, "Source") == 0)
proj.type = ProjectorType::Source;
else if (astrcmpi(type, "Scene") == 0)
proj.type = ProjectorType::Scene;
else if (astrcmpi(type, "StudioProgram") == 0)
proj.type = ProjectorType::StudioProgram;
else if (astrcmpi(type, "Multiview") == 0)
proj.type = ProjectorType::Multiview;
}
QMetaObject::invokeMethod(main, "OpenSavedProjector", WaitConnection(),
Q_ARG(SavedProjectorInfo *, &proj));
}
void obs_frontend_save(void) override { main->SaveProject(); }
void obs_frontend_defer_save_begin(void) override { QMetaObject::invokeMethod(main, "DeferSaveBegin"); }
void obs_frontend_defer_save_end(void) override { QMetaObject::invokeMethod(main, "DeferSaveEnd"); }
void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data) override
{
size_t idx = GetCallbackIdx(saveCallbacks, callback, private_data);
if (idx == (size_t)-1)
saveCallbacks.emplace_back(callback, private_data);
}
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data) override
{
size_t idx = GetCallbackIdx(saveCallbacks, callback, private_data);
if (idx == (size_t)-1)
return;
saveCallbacks.erase(saveCallbacks.begin() + idx);
}
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data) override
{
size_t idx = GetCallbackIdx(preloadCallbacks, callback, private_data);
if (idx == (size_t)-1)
preloadCallbacks.emplace_back(callback, private_data);
}
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data) override
{
size_t idx = GetCallbackIdx(preloadCallbacks, callback, private_data);
if (idx == (size_t)-1)
return;
preloadCallbacks.erase(preloadCallbacks.begin() + idx);
}
void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate) override
{
App()->PushUITranslation(translate);
}
void obs_frontend_pop_ui_translation(void) override { App()->PopUITranslation(); }
void obs_frontend_set_streaming_service(obs_service_t *service) override { main->SetService(service); }
obs_service_t *obs_frontend_get_streaming_service(void) override { return main->GetService(); }
void obs_frontend_save_streaming_service(void) override { main->SaveService(); }
bool obs_frontend_preview_program_mode_active(void) override { return main->IsPreviewProgramMode(); }
void obs_frontend_set_preview_program_mode(bool enable) override { main->SetPreviewProgramMode(enable); }
void obs_frontend_preview_program_trigger_transition(void) override
{
QMetaObject::invokeMethod(main, "TransitionClicked");
}
bool obs_frontend_preview_enabled(void) override { return main->previewEnabled; }
void obs_frontend_set_preview_enabled(bool enable) override
{
if (main->previewEnabled != enable)
main->EnablePreviewDisplay(enable);
}
obs_source_t *obs_frontend_get_current_preview_scene(void) override
{
if (main->IsPreviewProgramMode()) {
OBSSource source = main->GetCurrentSceneSource();
return obs_source_get_ref(source);
}
return nullptr;
}
void obs_frontend_set_current_preview_scene(obs_source_t *scene) override
{
if (main->IsPreviewProgramMode()) {
QMetaObject::invokeMethod(main, "SetCurrentScene", Q_ARG(OBSSource, OBSSource(scene)),
Q_ARG(bool, false));
}
}
void *obs_frontend_get_main_window(void) override;
void obs_frontend_take_screenshot(void) override { QMetaObject::invokeMethod(main, "Screenshot"); }
void *obs_frontend_get_main_window_handle(void) override;
void obs_frontend_take_source_screenshot(obs_source_t *source) override
{
QMetaObject::invokeMethod(main, "Screenshot", Q_ARG(OBSSource, OBSSource(source)));
}
void *obs_frontend_get_system_tray(void) override;
obs_output_t *obs_frontend_get_virtualcam_output(void) override
{
OBSOutput output = main->outputHandler->virtualCam.Get();
return obs_output_get_ref(output);
}
void obs_frontend_get_scenes(struct obs_frontend_source_list *sources) override;
void obs_frontend_start_virtualcam(void) override { QMetaObject::invokeMethod(main, "StartVirtualCam"); }
obs_source_t *obs_frontend_get_current_scene(void) override;
void obs_frontend_stop_virtualcam(void) override { QMetaObject::invokeMethod(main, "StopVirtualCam"); }
void obs_frontend_set_current_scene(obs_source_t *scene) override;
bool obs_frontend_virtualcam_active(void) override { return os_atomic_load_bool(&virtualcam_active); }
void obs_frontend_get_transitions(struct obs_frontend_source_list *sources) override;
void obs_frontend_reset_video(void) override { main->ResetVideo(); }
obs_source_t *obs_frontend_get_current_transition(void) override;
void obs_frontend_open_source_properties(obs_source_t *source) override
{
QMetaObject::invokeMethod(main, "OpenProperties", Q_ARG(OBSSource, OBSSource(source)));
}
void obs_frontend_set_current_transition(obs_source_t *transition) override;
void obs_frontend_open_source_filters(obs_source_t *source) override
{
QMetaObject::invokeMethod(main, "OpenFilters", Q_ARG(OBSSource, OBSSource(source)));
}
int obs_frontend_get_transition_duration(void) override;
void obs_frontend_open_source_interaction(obs_source_t *source) override
{
QMetaObject::invokeMethod(main, "OpenInteraction", Q_ARG(OBSSource, OBSSource(source)));
}
void obs_frontend_set_transition_duration(int duration) override;
void obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item) override
{
QMetaObject::invokeMethod(main, "OpenEditTransform", Q_ARG(OBSSceneItem, OBSSceneItem(item)));
}
void obs_frontend_release_tbar(void) override;
char *obs_frontend_get_current_record_output_path(void) override
{
const char *recordOutputPath = main->GetCurrentOutputPath();
void obs_frontend_set_tbar_position(int position) override;
return bstrdup(recordOutputPath);
}
int obs_frontend_get_tbar_position(void) override;
const char *obs_frontend_get_locale_string(const char *string) override { return Str(string); }
void obs_frontend_get_scene_collections(std::vector<std::string> &strings) override;
bool obs_frontend_is_theme_dark(void) override { return App()->IsThemeDark(); }
char *obs_frontend_get_current_scene_collection(void) override;
char *obs_frontend_get_last_recording(void) override
{
return bstrdup(main->outputHandler->lastRecordingPath.c_str());
}
void obs_frontend_set_current_scene_collection(const char *collection) override;
char *obs_frontend_get_last_screenshot(void) override { return bstrdup(main->lastScreenshot.c_str()); }
bool obs_frontend_add_scene_collection(const char *name) override;
char *obs_frontend_get_last_replay(void) override { return bstrdup(main->lastReplay.c_str()); }
void obs_frontend_get_profiles(std::vector<std::string> &strings) override;
char *obs_frontend_get_current_profile(void) override;
char *obs_frontend_get_current_profile_path(void) override;
void obs_frontend_set_current_profile(const char *profile) override;
void obs_frontend_create_profile(const char *name) override;
void obs_frontend_duplicate_profile(const char *name) override;
void obs_frontend_delete_profile(const char *profile) override;
void obs_frontend_streaming_start(void) override;
void obs_frontend_streaming_stop(void) override;
bool obs_frontend_streaming_active(void) override;
void obs_frontend_recording_start(void) override;
void obs_frontend_recording_stop(void) override;
bool obs_frontend_recording_active(void) override;
void obs_frontend_recording_pause(bool pause) override;
bool obs_frontend_recording_paused(void) override;
bool obs_frontend_recording_split_file(void) override;
bool obs_frontend_recording_add_chapter(const char *name) override;
void obs_frontend_replay_buffer_start(void) override;
void obs_frontend_replay_buffer_save(void) override;
void obs_frontend_replay_buffer_stop(void) override;
bool obs_frontend_replay_buffer_active(void) override;
void *obs_frontend_add_tools_menu_qaction(const char *name) override;
void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback, void *private_data) override;
void *obs_frontend_add_dock(void *dock) override;
bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget) override;
void obs_frontend_remove_dock(const char *id) override;
bool obs_frontend_add_custom_qdock(const char *id, void *dock) override;
void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data) override;
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data) override;
obs_output_t *obs_frontend_get_streaming_output(void) override;
obs_output_t *obs_frontend_get_recording_output(void) override;
obs_output_t *obs_frontend_get_replay_buffer_output(void) override;
config_t *obs_frontend_get_profile_config(void) override;
config_t *obs_frontend_get_global_config(void) override;
config_t *obs_frontend_get_app_config(void) override;
config_t *obs_frontend_get_user_config(void) override;
void obs_frontend_open_projector(const char *type, int monitor, const char *geometry,
const char *name) override;
void obs_frontend_save(void) override;
void obs_frontend_defer_save_begin(void) override;
void obs_frontend_defer_save_end(void) override;
void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data) override;
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data) override;
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data) override;
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data) override;
void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate) override;
void obs_frontend_pop_ui_translation(void) override;
void obs_frontend_set_streaming_service(obs_service_t *service) override;
obs_service_t *obs_frontend_get_streaming_service(void) override;
void obs_frontend_save_streaming_service(void) override;
bool obs_frontend_preview_program_mode_active(void) override;
void obs_frontend_set_preview_program_mode(bool enable) override;
void obs_frontend_preview_program_trigger_transition(void) override;
bool obs_frontend_preview_enabled(void) override;
void obs_frontend_set_preview_enabled(bool enable) override;
obs_source_t *obs_frontend_get_current_preview_scene(void) override;
void obs_frontend_set_current_preview_scene(obs_source_t *scene) override;
void obs_frontend_take_screenshot(void) override;
void obs_frontend_take_source_screenshot(obs_source_t *source) override;
obs_output_t *obs_frontend_get_virtualcam_output(void) override;
void obs_frontend_start_virtualcam(void) override;
void obs_frontend_stop_virtualcam(void) override;
bool obs_frontend_virtualcam_active(void) override;
void obs_frontend_reset_video(void) override;
void obs_frontend_open_source_properties(obs_source_t *source) override;
void obs_frontend_open_source_filters(obs_source_t *source) override;
void obs_frontend_open_source_interaction(obs_source_t *source) override;
void obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item) override;
char *obs_frontend_get_current_record_output_path(void) override;
const char *obs_frontend_get_locale_string(const char *string) override;
bool obs_frontend_is_theme_dark(void) override;
char *obs_frontend_get_last_recording(void) override;
char *obs_frontend_get_last_screenshot(void) override;
char *obs_frontend_get_last_replay(void) override;
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) override
{
main->undo_s.add_action(
name, [undo](const std::string &data) { undo(data.c_str()); },
[redo](const std::string &data) { redo(data.c_str()); }, undo_data, redo_data, repeatable);
}
const char *undo_data, const char *redo_data, bool repeatable) override;
void on_load(obs_data_t *settings) override
{
for (size_t i = saveCallbacks.size(); i > 0; i--) {
auto cb = saveCallbacks[i - 1];
cb.callback(settings, false, cb.private_data);
}
}
void on_load(obs_data_t *settings) override;
void on_preload(obs_data_t *settings) override
{
for (size_t i = preloadCallbacks.size(); i > 0; i--) {
auto cb = preloadCallbacks[i - 1];
cb.callback(settings, false, cb.private_data);
}
}
void on_preload(obs_data_t *settings) override;
void on_save(obs_data_t *settings) override
{
for (size_t i = saveCallbacks.size(); i > 0; i--) {
auto cb = saveCallbacks[i - 1];
cb.callback(settings, true, cb.private_data);
}
}
void on_save(obs_data_t *settings) override;
void on_event(enum obs_frontend_event event) override
{
if (main->disableSaving && event != OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP &&
event != OBS_FRONTEND_EVENT_EXIT)
return;
for (size_t i = callbacks.size(); i > 0; i--) {
auto cb = callbacks[i - 1];
cb.callback(event, cb.private_data);
}
}
void on_event(enum obs_frontend_event event) override;
};
obs_frontend_callbacks *InitializeAPIInterface(OBSBasic *main)
{
obs_frontend_callbacks *api = new OBSStudioAPI(main);
obs_frontend_set_callbacks_internal(api);
return api;
}
obs_frontend_callbacks *InitializeAPIInterface(OBSBasic *main);

File diff suppressed because it is too large Load Diff

View File

@ -17,41 +17,7 @@
#pragma once
#include <QApplication>
#include <QTranslator>
#include <QPointer>
#include <QFileSystemWatcher>
#ifndef _WIN32
#include <QSocketNotifier>
#else
#include <QSessionManager>
#endif
#include <obs.hpp>
#include <util/lexer.h>
#include <util/profiler.h>
#include <util/util.hpp>
#include <util/platform.h>
#include <obs-frontend-api.h>
#include <functional>
#include <string>
#include <memory>
#include <vector>
#include <deque>
#include <filesystem>
#include "window-main.hpp"
#include "obs-app-theming.hpp"
std::string CurrentTimeString();
std::string CurrentDateTimeString();
std::string GenerateTimeDateFilename(const char *extension, bool noSpace = false);
std::string GenerateSpecifiedFilename(const char *extension, bool noSpace, const char *format);
std::string GetFormatString(const char *format, const char *prefix, const char *suffix);
std::string GetFormatExt(const char *container);
std::string GetOutputFilename(const char *path, const char *container, bool noSpace, bool overwrite,
const char *format);
QObject *CreateShortcutFilter();
struct BaseLexer {
lexer lex;
@ -61,220 +27,3 @@ public:
inline ~BaseLexer() { lexer_free(&lex); }
operator lexer *() { return &lex; }
};
class OBSTranslator : public QTranslator {
Q_OBJECT
public:
virtual bool isEmpty() const override { return false; }
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation,
int n) const override;
};
typedef std::function<void()> VoidFunc;
struct UpdateBranch {
QString name;
QString display_name;
QString description;
bool is_enabled;
bool is_visible;
};
class OBSApp : public QApplication {
Q_OBJECT
private:
std::string locale;
ConfigFile appConfig;
ConfigFile userConfig;
TextLookup textLookup;
QPointer<OBSMainWindow> mainWindow;
profiler_name_store_t *profilerNameStore = nullptr;
std::vector<UpdateBranch> updateBranches;
bool branches_loaded = false;
bool libobs_initialized = false;
os_inhibit_t *sleepInhibitor = nullptr;
int sleepInhibitRefs = 0;
bool enableHotkeysInFocus = true;
bool enableHotkeysOutOfFocus = true;
std::deque<obs_frontend_translate_ui_cb> translatorHooks;
bool UpdatePre22MultiviewLayout(const char *layout);
bool InitGlobalConfig();
bool InitGlobalConfigDefaults();
bool InitGlobalLocationDefaults();
bool MigrateGlobalSettings();
void MigrateLegacySettings(uint32_t lastVersion);
bool InitUserConfig(std::filesystem::path &userConfigLocation, uint32_t lastVersion);
void InitUserConfigDefaults();
bool InitLocale();
bool InitTheme();
inline void ResetHotkeyState(bool inFocus);
QPalette defaultPalette;
OBSTheme *currentTheme = nullptr;
QHash<QString, OBSTheme> themes;
QPointer<QFileSystemWatcher> themeWatcher;
void FindThemes();
bool notify(QObject *receiver, QEvent *e) override;
#ifndef _WIN32
static int sigintFd[2];
QSocketNotifier *snInt = nullptr;
#else
private slots:
void commitData(QSessionManager &manager);
#endif
private slots:
void themeFileChanged(const QString &);
public:
OBSApp(int &argc, char **argv, profiler_name_store_t *store);
~OBSApp();
void AppInit();
bool OBSInit();
void UpdateHotkeyFocusSetting(bool reset = true);
void DisableHotkeys();
inline bool HotkeysEnabledInFocus() const { return enableHotkeysInFocus; }
inline QMainWindow *GetMainWindow() const { return mainWindow.data(); }
inline config_t *GetAppConfig() const { return appConfig; }
inline config_t *GetUserConfig() const { return userConfig; }
std::filesystem::path userConfigLocation;
std::filesystem::path userScenesLocation;
std::filesystem::path userProfilesLocation;
inline const char *GetLocale() const { return locale.c_str(); }
OBSTheme *GetTheme() const { return currentTheme; }
QList<OBSTheme> GetThemes() const { return themes.values(); }
OBSTheme *GetTheme(const QString &name);
bool SetTheme(const QString &name);
bool IsThemeDark() const { return currentTheme ? currentTheme->isDark : false; }
void SetBranchData(const std::string &data);
std::vector<UpdateBranch> GetBranches();
inline lookup_t *GetTextLookup() const { return textLookup; }
inline const char *GetString(const char *lookupVal) const { return textLookup.GetString(lookupVal); }
bool TranslateString(const char *lookupVal, const char **out) const;
profiler_name_store_t *GetProfilerNameStore() const { return profilerNameStore; }
const char *GetLastLog() const;
const char *GetCurrentLog() const;
const char *GetLastCrashLog() const;
std::string GetVersionString(bool platform = true) const;
bool IsPortableMode();
bool IsUpdaterDisabled();
bool IsMissingFilesCheckDisabled();
const char *InputAudioSource() const;
const char *OutputAudioSource() const;
const char *GetRenderModule() const;
inline void IncrementSleepInhibition()
{
if (!sleepInhibitor)
return;
if (sleepInhibitRefs++ == 0)
os_inhibit_sleep_set_active(sleepInhibitor, true);
}
inline void DecrementSleepInhibition()
{
if (!sleepInhibitor)
return;
if (sleepInhibitRefs == 0)
return;
if (--sleepInhibitRefs == 0)
os_inhibit_sleep_set_active(sleepInhibitor, false);
}
inline void PushUITranslation(obs_frontend_translate_ui_cb cb) { translatorHooks.emplace_front(cb); }
inline void PopUITranslation() { translatorHooks.pop_front(); }
#ifndef _WIN32
static void SigIntSignalHandler(int);
#endif
public slots:
void Exec(VoidFunc func);
void ProcessSigInt();
signals:
void StyleChanged();
};
int GetAppConfigPath(char *path, size_t size, const char *name);
char *GetAppConfigPathPtr(const char *name);
int GetProgramDataPath(char *path, size_t size, const char *name);
char *GetProgramDataPathPtr(const char *name);
inline OBSApp *App()
{
return static_cast<OBSApp *>(qApp);
}
std::vector<std::pair<std::string, std::string>> GetLocaleNames();
inline const char *Str(const char *lookup)
{
return App()->GetString(lookup);
}
inline QString QTStr(const char *lookupVal)
{
return QString::fromUtf8(Str(lookupVal));
}
bool GetFileSafeName(const char *name, std::string &file);
bool GetClosestUnusedFileName(std::string &path, const char *extension);
bool GetUnusedSceneCollectionFile(std::string &name, std::string &file);
bool WindowPositionValid(QRect rect);
extern bool portable_mode;
extern bool steam;
extern bool safe_mode;
extern bool disable_3p_plugins;
extern bool opt_start_streaming;
extern bool opt_start_recording;
extern bool opt_start_replaybuffer;
extern bool opt_start_virtualcam;
extern bool opt_minimize_tray;
extern bool opt_studio_mode;
extern bool opt_allow_opengl;
extern bool opt_always_on_top;
extern std::string opt_starting_scene;
extern bool restart;
extern bool restart_safe;
#ifdef _WIN32
extern "C" void install_dll_blocklist_hook(void);
extern "C" void log_blocked_dlls(void);
#endif

View File

@ -17,12 +17,11 @@
#pragma once
#include <QVariant>
#include <QString>
#include <QStringList>
#include <filesystem>
struct OBSThemeVariable;
struct OBSTheme {
/* internal name, must be unique */
QString id;
@ -43,24 +42,3 @@ struct OBSTheme {
bool isBaseTheme; /* Whether it is a "style" or variant */
bool isHighContrast; /* Whether it is a high-contrast adjustment layer */
};
struct OBSThemeVariable {
enum VariableType {
Color, /* RGB color value*/
Size, /* Number with suffix denoting size (e.g. px, pt, em) */
Number, /* Number without suffix */
String, /* Raw string (e.g. color name, border style, etc.) */
Alias, /* Points at another variable, value will be the key */
Calc, /* Simple calculation with two operands */
};
/* Whether the variable should be editable in the UI */
bool editable = false;
/* Used for VariableType::Size only */
QString suffix;
VariableType type;
QString name;
QVariant value;
QVariant userValue; /* If overwritten by user, use this value instead */
};

View File

@ -17,33 +17,9 @@
#pragma once
#include <QString>
#include <QVariant>
#include <filesystem>
struct OBSThemeVariable;
struct OBSTheme {
/* internal name, must be unique */
QString id;
QString name;
QString author;
QString extends;
/* First ancestor base theme */
QString parent;
/* Dependencies from root to direct ancestor */
QStringList dependencies;
/* File path */
std::filesystem::path location;
std::filesystem::path filename; /* Filename without extension */
bool isDark;
bool isVisible; /* Whether it should be shown to the user */
bool isBaseTheme; /* Whether it is a "style" or variant */
bool isHighContrast; /* Whether it is a high-contrast adjustment layer */
};
struct OBSThemeVariable {
enum VariableType {
Color, /* RGB color value*/

File diff suppressed because it is too large Load Diff

View File

@ -17,50 +17,8 @@
#pragma once
#include <QApplication>
#include <QString>
#include <QTranslator>
#include <QPointer>
#include <QFileSystemWatcher>
#ifndef _WIN32
#include <QSocketNotifier>
#else
#include <QSessionManager>
#endif
#include <obs.hpp>
#include <util/lexer.h>
#include <util/profiler.h>
#include <util/util.hpp>
#include <util/platform.h>
#include <obs-frontend-api.h>
#include <functional>
#include <string>
#include <memory>
#include <vector>
#include <deque>
#include <filesystem>
#include "window-main.hpp"
#include "obs-app-theming.hpp"
std::string CurrentTimeString();
std::string CurrentDateTimeString();
std::string GenerateTimeDateFilename(const char *extension, bool noSpace = false);
std::string GenerateSpecifiedFilename(const char *extension, bool noSpace, const char *format);
std::string GetFormatString(const char *format, const char *prefix, const char *suffix);
std::string GetFormatExt(const char *container);
std::string GetOutputFilename(const char *path, const char *container, bool noSpace, bool overwrite,
const char *format);
QObject *CreateShortcutFilter();
struct BaseLexer {
lexer lex;
public:
inline BaseLexer() { lexer_init(&lex); }
inline ~BaseLexer() { lexer_free(&lex); }
operator lexer *() { return &lex; }
};
class OBSTranslator : public QTranslator {
Q_OBJECT
@ -71,210 +29,3 @@ public:
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation,
int n) const override;
};
typedef std::function<void()> VoidFunc;
struct UpdateBranch {
QString name;
QString display_name;
QString description;
bool is_enabled;
bool is_visible;
};
class OBSApp : public QApplication {
Q_OBJECT
private:
std::string locale;
ConfigFile appConfig;
ConfigFile userConfig;
TextLookup textLookup;
QPointer<OBSMainWindow> mainWindow;
profiler_name_store_t *profilerNameStore = nullptr;
std::vector<UpdateBranch> updateBranches;
bool branches_loaded = false;
bool libobs_initialized = false;
os_inhibit_t *sleepInhibitor = nullptr;
int sleepInhibitRefs = 0;
bool enableHotkeysInFocus = true;
bool enableHotkeysOutOfFocus = true;
std::deque<obs_frontend_translate_ui_cb> translatorHooks;
bool UpdatePre22MultiviewLayout(const char *layout);
bool InitGlobalConfig();
bool InitGlobalConfigDefaults();
bool InitGlobalLocationDefaults();
bool MigrateGlobalSettings();
void MigrateLegacySettings(uint32_t lastVersion);
bool InitUserConfig(std::filesystem::path &userConfigLocation, uint32_t lastVersion);
void InitUserConfigDefaults();
bool InitLocale();
bool InitTheme();
inline void ResetHotkeyState(bool inFocus);
QPalette defaultPalette;
OBSTheme *currentTheme = nullptr;
QHash<QString, OBSTheme> themes;
QPointer<QFileSystemWatcher> themeWatcher;
void FindThemes();
bool notify(QObject *receiver, QEvent *e) override;
#ifndef _WIN32
static int sigintFd[2];
QSocketNotifier *snInt = nullptr;
#else
private slots:
void commitData(QSessionManager &manager);
#endif
private slots:
void themeFileChanged(const QString &);
public:
OBSApp(int &argc, char **argv, profiler_name_store_t *store);
~OBSApp();
void AppInit();
bool OBSInit();
void UpdateHotkeyFocusSetting(bool reset = true);
void DisableHotkeys();
inline bool HotkeysEnabledInFocus() const { return enableHotkeysInFocus; }
inline QMainWindow *GetMainWindow() const { return mainWindow.data(); }
inline config_t *GetAppConfig() const { return appConfig; }
inline config_t *GetUserConfig() const { return userConfig; }
std::filesystem::path userConfigLocation;
std::filesystem::path userScenesLocation;
std::filesystem::path userProfilesLocation;
inline const char *GetLocale() const { return locale.c_str(); }
OBSTheme *GetTheme() const { return currentTheme; }
QList<OBSTheme> GetThemes() const { return themes.values(); }
OBSTheme *GetTheme(const QString &name);
bool SetTheme(const QString &name);
bool IsThemeDark() const { return currentTheme ? currentTheme->isDark : false; }
void SetBranchData(const std::string &data);
std::vector<UpdateBranch> GetBranches();
inline lookup_t *GetTextLookup() const { return textLookup; }
inline const char *GetString(const char *lookupVal) const { return textLookup.GetString(lookupVal); }
bool TranslateString(const char *lookupVal, const char **out) const;
profiler_name_store_t *GetProfilerNameStore() const { return profilerNameStore; }
const char *GetLastLog() const;
const char *GetCurrentLog() const;
const char *GetLastCrashLog() const;
std::string GetVersionString(bool platform = true) const;
bool IsPortableMode();
bool IsUpdaterDisabled();
bool IsMissingFilesCheckDisabled();
const char *InputAudioSource() const;
const char *OutputAudioSource() const;
const char *GetRenderModule() const;
inline void IncrementSleepInhibition()
{
if (!sleepInhibitor)
return;
if (sleepInhibitRefs++ == 0)
os_inhibit_sleep_set_active(sleepInhibitor, true);
}
inline void DecrementSleepInhibition()
{
if (!sleepInhibitor)
return;
if (sleepInhibitRefs == 0)
return;
if (--sleepInhibitRefs == 0)
os_inhibit_sleep_set_active(sleepInhibitor, false);
}
inline void PushUITranslation(obs_frontend_translate_ui_cb cb) { translatorHooks.emplace_front(cb); }
inline void PopUITranslation() { translatorHooks.pop_front(); }
#ifndef _WIN32
static void SigIntSignalHandler(int);
#endif
public slots:
void Exec(VoidFunc func);
void ProcessSigInt();
signals:
void StyleChanged();
};
int GetAppConfigPath(char *path, size_t size, const char *name);
char *GetAppConfigPathPtr(const char *name);
int GetProgramDataPath(char *path, size_t size, const char *name);
char *GetProgramDataPathPtr(const char *name);
inline OBSApp *App()
{
return static_cast<OBSApp *>(qApp);
}
std::vector<std::pair<std::string, std::string>> GetLocaleNames();
inline const char *Str(const char *lookup)
{
return App()->GetString(lookup);
}
inline QString QTStr(const char *lookupVal)
{
return QString::fromUtf8(Str(lookupVal));
}
bool GetFileSafeName(const char *name, std::string &file);
bool GetClosestUnusedFileName(std::string &path, const char *extension);
bool GetUnusedSceneCollectionFile(std::string &name, std::string &file);
bool WindowPositionValid(QRect rect);
extern bool portable_mode;
extern bool steam;
extern bool safe_mode;
extern bool disable_3p_plugins;
extern bool opt_start_streaming;
extern bool opt_start_recording;
extern bool opt_start_replaybuffer;
extern bool opt_start_virtualcam;
extern bool opt_minimize_tray;
extern bool opt_studio_mode;
extern bool opt_allow_opengl;
extern bool opt_always_on_top;
extern std::string opt_starting_scene;
extern bool restart;
extern bool restart_safe;
#ifdef _WIN32
extern "C" void install_dll_blocklist_hook(void);
extern "C" void log_blocked_dlls(void);
#endif