UI: Add front-end API library
Allows manipulating and modifying the front-end via plugins.
This commit is contained in:
parent
bfc21317bf
commit
8836592d92
@ -1,5 +1,3 @@
|
||||
project(obs)
|
||||
|
||||
option(ENABLE_UI "Enables the OBS user interfaces" ON)
|
||||
if(DISABLE_UI)
|
||||
message(STATUS "UI disabled")
|
||||
@ -10,6 +8,12 @@ else()
|
||||
set(FIND_MODE QUIET)
|
||||
endif()
|
||||
|
||||
add_subdirectory(obs-frontend-api)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
project(obs)
|
||||
|
||||
if(DEFINED QTDIR${_lib_suffix})
|
||||
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
|
||||
elseif(DEFINED QTDIR)
|
||||
@ -40,6 +44,7 @@ if(NOT Qt5Widgets_FOUND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM "obs-frontend-api")
|
||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
|
||||
|
||||
find_package(Libcurl REQUIRED)
|
||||
@ -97,6 +102,7 @@ endif()
|
||||
set(obs_SOURCES
|
||||
${obs_PLATFORM_SOURCES}
|
||||
obs-app.cpp
|
||||
api-interface.cpp
|
||||
window-basic-main.cpp
|
||||
window-basic-filters.cpp
|
||||
window-basic-settings.cpp
|
||||
@ -219,6 +225,7 @@ target_link_libraries(obs
|
||||
libobs
|
||||
libff
|
||||
Qt5::Widgets
|
||||
obs-frontend-api
|
||||
${LIBCURL_LIBRARIES}
|
||||
${obs_PLATFORM_LIBRARIES})
|
||||
|
||||
|
362
UI/api-interface.cpp
Normal file
362
UI/api-interface.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
#include <obs-frontend-internal.hpp>
|
||||
#include "obs-app.hpp"
|
||||
#include "qt-wrappers.hpp"
|
||||
#include "window-basic-main.hpp"
|
||||
#include "window-basic-main-outputs.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
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>();
|
||||
}
|
||||
|
||||
void EnumProfiles(function<bool (const char *, const char *)> &&cb);
|
||||
void EnumSceneCollections(function<bool (const char *, const char *)> &&cb);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
template<typename T> struct OBSStudioCallback {
|
||||
T callback;
|
||||
void *private_data;
|
||||
|
||||
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;
|
||||
vector<OBSStudioCallback<obs_frontend_save_cb>> saveCallbacks;
|
||||
|
||||
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_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);
|
||||
|
||||
obs_source_addref(source);
|
||||
da_push_back(sources->sources, &source);
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_scene(void) override
|
||||
{
|
||||
OBSSource source;
|
||||
|
||||
if (main->IsPreviewProgramMode()) {
|
||||
source = obs_weak_source_get_source(main->programScene);
|
||||
} else {
|
||||
source = main->GetCurrentSceneSource();
|
||||
obs_source_addref(source);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene(obs_source_t *scene) override
|
||||
{
|
||||
if (main->IsPreviewProgramMode()) {
|
||||
QMetaObject::invokeMethod(main, "TransitionToScene",
|
||||
Q_ARG(OBSSource, OBSSource(scene)));
|
||||
} else {
|
||||
QMetaObject::invokeMethod(main, "SetCurrentScene",
|
||||
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>();
|
||||
|
||||
obs_source_addref(tr);
|
||||
da_push_back(sources->sources, &tr);
|
||||
}
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_transition(void) override
|
||||
{
|
||||
OBSSource tr = main->GetCurrentTransition();
|
||||
|
||||
obs_source_addref(tr);
|
||||
return tr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_transition(
|
||||
obs_source_t *transition) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "SetTransition",
|
||||
Q_ARG(OBSSource, OBSSource(transition)));
|
||||
}
|
||||
|
||||
void obs_frontend_get_scene_collections(
|
||||
std::vector<std::string> &strings) override
|
||||
{
|
||||
auto addCollection = [&](const char *name, const char *)
|
||||
{
|
||||
strings.emplace_back(name);
|
||||
return true;
|
||||
};
|
||||
|
||||
EnumSceneCollections(addCollection);
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_scene_collection(void) override
|
||||
{
|
||||
const char *cur_name = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
return bstrdup(cur_name);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_get_profiles(
|
||||
std::vector<std::string> &strings) override
|
||||
{
|
||||
auto addProfile = [&](const char *name, const char *)
|
||||
{
|
||||
strings.emplace_back(name);
|
||||
return true;
|
||||
};
|
||||
|
||||
EnumProfiles(addProfile);
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_profile(void) override
|
||||
{
|
||||
const char *name = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "Profile");
|
||||
return bstrdup(name);
|
||||
}
|
||||
|
||||
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_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 main->outputHandler->StreamingActive();
|
||||
}
|
||||
|
||||
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 main->outputHandler->StreamingActive();
|
||||
}
|
||||
|
||||
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_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
|
||||
{
|
||||
OBSOutput output = main->outputHandler->streamOutput;
|
||||
obs_output_addref(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_recording_output(void) override
|
||||
{
|
||||
OBSOutput out = main->outputHandler->fileOutput;
|
||||
obs_output_addref(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_profile_config(void) override
|
||||
{
|
||||
return main->basicConfig;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_global_config(void) override
|
||||
{
|
||||
return App()->GlobalConfig();
|
||||
}
|
||||
|
||||
void obs_frontend_save(void) override
|
||||
{
|
||||
main->SaveProject();
|
||||
}
|
||||
|
||||
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_push_ui_translation(
|
||||
obs_frontend_translate_ui_cb translate) override
|
||||
{
|
||||
App()->PushUITranslation(translate);
|
||||
}
|
||||
|
||||
void obs_frontend_pop_ui_translation(void) override
|
||||
{
|
||||
App()->PopUITranslation();
|
||||
}
|
||||
|
||||
void on_load(obs_data_t *settings) override
|
||||
{
|
||||
for (auto cb : saveCallbacks)
|
||||
cb.callback(settings, false, cb.private_data);
|
||||
}
|
||||
|
||||
void on_save(obs_data_t *settings) override
|
||||
{
|
||||
for (auto cb : saveCallbacks)
|
||||
cb.callback(settings, true, cb.private_data);
|
||||
}
|
||||
|
||||
void on_event(enum obs_frontend_event event) override
|
||||
{
|
||||
if (main->disableSaving)
|
||||
return;
|
||||
|
||||
for (auto cb : callbacks)
|
||||
cb.callback(event, cb.private_data);
|
||||
}
|
||||
};
|
||||
|
||||
obs_frontend_callbacks *InitializeAPIInterface(OBSBasic *main)
|
||||
{
|
||||
obs_frontend_callbacks *api = new OBSStudioAPI(main);
|
||||
obs_frontend_set_callbacks_internal(api);
|
||||
return api;
|
||||
}
|
@ -354,6 +354,9 @@ Basic.MainMenu.View.StatusBar="&Status Bar"
|
||||
Basic.MainMenu.SceneCollection="&Scene Collection"
|
||||
Basic.MainMenu.Profile="&Profile"
|
||||
|
||||
# basic mode help menu
|
||||
Basic.MainMenu.Tools="&Tools"
|
||||
|
||||
# basic mode help menu
|
||||
Basic.MainMenu.Help="&Help"
|
||||
Basic.MainMenu.Help.Website="Visit &Website"
|
||||
|
@ -229,7 +229,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>201</width>
|
||||
<width>215</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -913,11 +913,20 @@
|
||||
<addaction name="toggleSceneTransitions"/>
|
||||
<addaction name="toggleStatusBar"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Basic.MainMenu.Tools</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menuBasic_MainMenu_Edit"/>
|
||||
<addaction name="viewMenu"/>
|
||||
<addaction name="profileMenu"/>
|
||||
<addaction name="sceneCollectionMenu"/>
|
||||
<addaction name="menuTools"/>
|
||||
<addaction name="menuBasic_MainMenu_Help"/>
|
||||
</widget>
|
||||
<widget class="OBSBasicStatusBar" name="statusbar"/>
|
||||
|
@ -937,12 +937,22 @@ const char *OBSApp::GetCurrentLog() const
|
||||
return currentLogFile.c_str();
|
||||
}
|
||||
|
||||
bool OBSApp::TranslateString(const char *lookupVal, const char **out) const
|
||||
{
|
||||
for (obs_frontend_translate_ui_cb cb : translatorHooks) {
|
||||
if (cb(lookupVal, out))
|
||||
return true;
|
||||
}
|
||||
|
||||
return text_lookup_getstr(App()->GetTextLookup(), lookupVal, out);
|
||||
}
|
||||
|
||||
QString OBSTranslator::translate(const char *context, const char *sourceText,
|
||||
const char *disambiguation, int n) const
|
||||
{
|
||||
const char *out = nullptr;
|
||||
if (!text_lookup_getstr(App()->GetTextLookup(), sourceText, &out))
|
||||
return QString();
|
||||
if (!App()->TranslateString(sourceText, &out))
|
||||
return QString(sourceText);
|
||||
|
||||
UNUSED_PARAMETER(context);
|
||||
UNUSED_PARAMETER(disambiguation);
|
||||
|
@ -25,9 +25,11 @@
|
||||
#include <util/profiler.h>
|
||||
#include <util/util.hpp>
|
||||
#include <util/platform.h>
|
||||
#include <obs-frontend-api.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
#include "window-main.hpp"
|
||||
|
||||
@ -71,6 +73,8 @@ private:
|
||||
os_inhibit_t *sleepInhibitor = nullptr;
|
||||
int sleepInhibitRefs = 0;
|
||||
|
||||
std::deque<obs_frontend_translate_ui_cb> translatorHooks;
|
||||
|
||||
bool InitGlobalConfig();
|
||||
bool InitGlobalConfigDefaults();
|
||||
bool InitLocale();
|
||||
@ -102,6 +106,8 @@ public:
|
||||
return textLookup.GetString(lookupVal);
|
||||
}
|
||||
|
||||
bool TranslateString(const char *lookupVal, const char **out) const;
|
||||
|
||||
profiler_name_store_t *GetProfilerNameStore() const
|
||||
{
|
||||
return profilerNameStore;
|
||||
@ -131,6 +137,16 @@ public:
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
int GetConfigPath(char *path, size_t size, const char *name);
|
||||
|
20
UI/obs-frontend-api/CMakeLists.txt
Normal file
20
UI/obs-frontend-api/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
project(obs-frontend-api)
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
|
||||
|
||||
add_definitions(-DLIBOBS_EXPORTS)
|
||||
|
||||
set(obs-frontend-api_SOURCES
|
||||
obs-frontend-api.cpp)
|
||||
|
||||
set(obs-frontend-api_HEADERS
|
||||
obs-frontend-internal.hpp
|
||||
obs-frontend-api.h)
|
||||
|
||||
add_library(obs-frontend-api SHARED
|
||||
${obs-frontend-api_SOURCES}
|
||||
${obs-frontend-api_HEADERS})
|
||||
target_link_libraries(obs-frontend-api
|
||||
libobs)
|
||||
|
||||
install_obs_core(obs-frontend-api)
|
295
UI/obs-frontend-api/obs-frontend-api.cpp
Normal file
295
UI/obs-frontend-api/obs-frontend-api.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
#include "obs-frontend-internal.hpp"
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static unique_ptr<obs_frontend_callbacks> c;
|
||||
|
||||
void obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks)
|
||||
{
|
||||
c.reset(callbacks);
|
||||
}
|
||||
|
||||
static inline bool callbacks_valid_(const char *func_name)
|
||||
{
|
||||
if (!c) {
|
||||
blog(LOG_WARNING, "Tried to call %s with no callbacks!",
|
||||
func_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define callbacks_valid() callbacks_valid_(__FUNCTION__)
|
||||
|
||||
static char **convert_string_list(vector<string> &strings)
|
||||
{
|
||||
size_t size = 0;
|
||||
size_t string_data_offset = (strings.size() + 1) * sizeof(char*);
|
||||
uint8_t *out;
|
||||
char **ptr_list;
|
||||
char *string_data;
|
||||
|
||||
size += string_data_offset;
|
||||
|
||||
for (auto &str : strings)
|
||||
size += str.size() + 1;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
out = (uint8_t*)bmalloc(size);
|
||||
ptr_list = (char**)out;
|
||||
string_data = (char*)(out + string_data_offset);
|
||||
|
||||
for (auto &str : strings) {
|
||||
*ptr_list = string_data;
|
||||
memcpy(string_data, str.c_str(), str.size() + 1);
|
||||
|
||||
ptr_list++;
|
||||
string_data += str.size() + 1;
|
||||
}
|
||||
|
||||
*ptr_list = nullptr;
|
||||
return (char**)out;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void *obs_frontend_get_main_window(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_main_window()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void *obs_frontend_get_main_window_handle(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_main_window_handle()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
char **obs_frontend_get_scene_names(void)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
return NULL;
|
||||
|
||||
struct obs_frontend_source_list sources = {};
|
||||
vector<string> names;
|
||||
c->obs_frontend_get_scenes(&sources);
|
||||
|
||||
for (size_t i = 0; i < sources.sources.num; i++) {
|
||||
obs_source_t *source = sources.sources.array[i];
|
||||
const char *name = obs_source_get_name(source);
|
||||
names.emplace_back(name);
|
||||
}
|
||||
|
||||
obs_frontend_source_list_free(&sources);
|
||||
return convert_string_list(names);
|
||||
}
|
||||
|
||||
void obs_frontend_get_scenes(struct obs_frontend_source_list *sources)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_get_scenes(sources);
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_scene(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_scene()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene(obs_source_t *scene)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_set_current_scene(scene);
|
||||
}
|
||||
|
||||
void obs_frontend_get_transitions(struct obs_frontend_source_list *sources)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_get_transitions(sources);
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_transition(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_transition()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_transition(obs_source_t *transition)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_set_current_transition(transition);
|
||||
}
|
||||
|
||||
char **obs_frontend_get_scene_collections(void)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
return nullptr;
|
||||
|
||||
vector<string> strings;
|
||||
c->obs_frontend_get_scene_collections(strings);
|
||||
return convert_string_list(strings);
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_scene_collection(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_scene_collection()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene_collection(const char *collection)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_set_current_scene_collection(collection);
|
||||
}
|
||||
|
||||
char **obs_frontend_get_profiles(void)
|
||||
{
|
||||
if (!callbacks_valid())
|
||||
return nullptr;
|
||||
|
||||
vector<string> strings;
|
||||
c->obs_frontend_get_profiles(strings);
|
||||
return convert_string_list(strings);
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_profile(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_profile()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_profile(const char *profile)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_set_current_profile(profile);
|
||||
}
|
||||
|
||||
void obs_frontend_streaming_start(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_streaming_start();
|
||||
}
|
||||
|
||||
void obs_frontend_streaming_stop(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_streaming_stop();
|
||||
}
|
||||
|
||||
bool obs_frontend_streaming_active(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_streaming_active()
|
||||
: false;
|
||||
}
|
||||
|
||||
void obs_frontend_recording_start(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_recording_start();
|
||||
}
|
||||
|
||||
void obs_frontend_recording_stop(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_recording_stop();
|
||||
}
|
||||
|
||||
bool obs_frontend_recording_active(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_recording_active()
|
||||
: false;
|
||||
}
|
||||
|
||||
void *obs_frontend_add_tools_menu_qaction(const char *name)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_add_tools_menu_qaction(name)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_tools_menu_item(name, callback,
|
||||
private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data)
|
||||
{
|
||||
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())
|
||||
c->obs_frontend_remove_event_callback(callback, private_data);
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_streaming_output(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_streaming_output()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_recording_output(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_recording_output()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_profile_config(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_profile_config()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_global_config(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_global_config()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_save(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_save();
|
||||
}
|
||||
|
||||
void obs_frontend_add_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data)
|
||||
{
|
||||
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())
|
||||
c->obs_frontend_remove_save_callback(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_push_ui_translation(translate);
|
||||
}
|
||||
|
||||
void obs_frontend_pop_ui_translation(void)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_pop_ui_translation();
|
||||
}
|
134
UI/obs-frontend-api/obs-frontend-api.h
Normal file
134
UI/obs-frontend-api/obs-frontend-api.h
Normal file
@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <obs.h>
|
||||
#include <util/darray.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct config_data;
|
||||
typedef struct config_data config_t;
|
||||
|
||||
struct obs_data;
|
||||
typedef struct obs_data obs_data_t;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
struct obs_frontend_source_list {
|
||||
DARRAY(obs_source_t*) sources;
|
||||
};
|
||||
|
||||
static inline void obs_frontend_source_list_free(
|
||||
struct obs_frontend_source_list *source_list)
|
||||
{
|
||||
size_t num = source_list->sources.num;
|
||||
for (size_t i = 0; i < num; i++)
|
||||
obs_source_release(source_list->sources.array[i]);
|
||||
da_free(source_list->sources);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* NOTE: Functions that return char** string lists are a single allocation of
|
||||
* memory with pointers to itself. Free with a single call to bfree on the
|
||||
* base char** pointer. */
|
||||
|
||||
/* NOTE: User interface should not use typical Qt locale translation methods,
|
||||
* as the OBS UI bypasses it to use a custom translation implementation. Use
|
||||
* standard module translation methods, obs_module_text. For text in a Qt
|
||||
* window, use obs_frontend_push_ui_translation when the text is about to be
|
||||
* translated, and obs_frontend_pop_ui_translation when translation is
|
||||
* complete. */
|
||||
|
||||
EXPORT void *obs_frontend_get_main_window(void);
|
||||
EXPORT void *obs_frontend_get_main_window_handle(void);
|
||||
|
||||
EXPORT char **obs_frontend_get_scene_names(void);
|
||||
EXPORT void obs_frontend_get_scenes(struct obs_frontend_source_list *sources);
|
||||
EXPORT obs_source_t *obs_frontend_get_current_scene(void);
|
||||
EXPORT void obs_frontend_set_current_scene(obs_source_t *scene);
|
||||
|
||||
EXPORT void obs_frontend_get_transitions(
|
||||
struct obs_frontend_source_list *sources);
|
||||
EXPORT obs_source_t *obs_frontend_get_current_transition(void);
|
||||
EXPORT void obs_frontend_set_current_transition(obs_source_t *transition);
|
||||
|
||||
EXPORT char **obs_frontend_get_scene_collections(void);
|
||||
EXPORT char *obs_frontend_get_current_scene_collection(void);
|
||||
EXPORT void obs_frontend_set_current_scene_collection(const char *collection);
|
||||
|
||||
EXPORT char **obs_frontend_get_profiles(void);
|
||||
EXPORT char *obs_frontend_get_current_profile(void);
|
||||
EXPORT void obs_frontend_set_current_profile(const char *profile);
|
||||
|
||||
EXPORT void obs_frontend_streaming_start(void);
|
||||
EXPORT void obs_frontend_streaming_stop(void);
|
||||
EXPORT bool obs_frontend_streaming_active(void);
|
||||
|
||||
EXPORT void obs_frontend_recording_start(void);
|
||||
EXPORT void obs_frontend_recording_stop(void);
|
||||
EXPORT bool obs_frontend_recording_active(void);
|
||||
|
||||
typedef void (*obs_frontend_cb)(void *private_data);
|
||||
|
||||
EXPORT void *obs_frontend_add_tools_menu_qaction(const char *name);
|
||||
EXPORT void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback, void *private_data);
|
||||
|
||||
enum obs_frontend_event {
|
||||
OBS_FRONTEND_EVENT_STREAMING_STARTING,
|
||||
OBS_FRONTEND_EVENT_STREAMING_STARTED,
|
||||
OBS_FRONTEND_EVENT_STREAMING_STOPPING,
|
||||
OBS_FRONTEND_EVENT_STREAMING_STOPPED,
|
||||
OBS_FRONTEND_EVENT_RECORDING_STARTING,
|
||||
OBS_FRONTEND_EVENT_RECORDING_STARTED,
|
||||
OBS_FRONTEND_EVENT_RECORDING_STOPPING,
|
||||
OBS_FRONTEND_EVENT_RECORDING_STOPPED,
|
||||
OBS_FRONTEND_EVENT_SCENE_CHANGED,
|
||||
OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED,
|
||||
OBS_FRONTEND_EVENT_TRANSITION_CHANGED,
|
||||
OBS_FRONTEND_EVENT_TRANSITION_STOPPED,
|
||||
OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED,
|
||||
OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED,
|
||||
OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED,
|
||||
OBS_FRONTEND_EVENT_PROFILE_CHANGED,
|
||||
OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED,
|
||||
OBS_FRONTEND_EVENT_EXIT
|
||||
};
|
||||
|
||||
typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event,
|
||||
void *private_data);
|
||||
|
||||
EXPORT void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_remove_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data);
|
||||
|
||||
typedef void (*obs_frontend_save_cb)(obs_data_t *save_data, bool saving,
|
||||
void *private_data);
|
||||
|
||||
EXPORT void obs_frontend_save(void);
|
||||
EXPORT void obs_frontend_add_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_remove_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data);
|
||||
|
||||
EXPORT obs_output_t *obs_frontend_get_streaming_output(void);
|
||||
EXPORT obs_output_t *obs_frontend_get_recording_output(void);
|
||||
|
||||
EXPORT config_t *obs_frontend_get_profile_config(void);
|
||||
EXPORT config_t *obs_frontend_get_global_config(void);
|
||||
|
||||
typedef bool (*obs_frontend_translate_ui_cb)(const char *text,
|
||||
const char **out);
|
||||
|
||||
EXPORT void obs_frontend_push_ui_translation(
|
||||
obs_frontend_translate_ui_cb translate);
|
||||
EXPORT void obs_frontend_pop_ui_translation(void);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
73
UI/obs-frontend-api/obs-frontend-internal.hpp
Normal file
73
UI/obs-frontend-api/obs-frontend-internal.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "obs-frontend-api.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
struct obs_frontend_callbacks {
|
||||
virtual void *obs_frontend_get_main_window(void)=0;
|
||||
virtual void *obs_frontend_get_main_window_handle(void)=0;
|
||||
|
||||
virtual void obs_frontend_get_scenes(
|
||||
struct obs_frontend_source_list *sources)=0;
|
||||
virtual obs_source_t *obs_frontend_get_current_scene(void)=0;
|
||||
virtual void obs_frontend_set_current_scene(obs_source_t *scene)=0;
|
||||
|
||||
virtual void obs_frontend_get_transitions(
|
||||
struct obs_frontend_source_list *sources)=0;
|
||||
virtual obs_source_t *obs_frontend_get_current_transition(void)=0;
|
||||
virtual void obs_frontend_set_current_transition(
|
||||
obs_source_t *transition)=0;
|
||||
|
||||
virtual void obs_frontend_get_scene_collections(
|
||||
std::vector<std::string> &strings)=0;
|
||||
virtual char *obs_frontend_get_current_scene_collection(void)=0;
|
||||
virtual void obs_frontend_set_current_scene_collection(
|
||||
const char *collection)=0;
|
||||
|
||||
virtual void obs_frontend_get_profiles(
|
||||
std::vector<std::string> &strings)=0;
|
||||
virtual char *obs_frontend_get_current_profile(void)=0;
|
||||
virtual void obs_frontend_set_current_profile(const char *profile)=0;
|
||||
|
||||
virtual void obs_frontend_streaming_start(void)=0;
|
||||
virtual void obs_frontend_streaming_stop(void)=0;
|
||||
virtual bool obs_frontend_streaming_active(void)=0;
|
||||
|
||||
virtual void obs_frontend_recording_start(void)=0;
|
||||
virtual void obs_frontend_recording_stop(void)=0;
|
||||
virtual bool obs_frontend_recording_active(void)=0;
|
||||
|
||||
virtual void *obs_frontend_add_tools_menu_qaction(const char *name)=0;
|
||||
virtual void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback, void *private_data)=0;
|
||||
|
||||
virtual void obs_frontend_add_event_callback(
|
||||
obs_frontend_event_cb callback, void *private_data)=0;
|
||||
virtual void obs_frontend_remove_event_callback(
|
||||
obs_frontend_event_cb callback, void *private_data)=0;
|
||||
|
||||
virtual obs_output_t *obs_frontend_get_streaming_output(void)=0;
|
||||
virtual obs_output_t *obs_frontend_get_recording_output(void)=0;
|
||||
|
||||
virtual config_t *obs_frontend_get_profile_config(void)=0;
|
||||
virtual config_t *obs_frontend_get_global_config(void)=0;
|
||||
|
||||
virtual void obs_frontend_save(void)=0;
|
||||
virtual void obs_frontend_add_save_callback(
|
||||
obs_frontend_save_cb callback, void *private_data)=0;
|
||||
virtual void obs_frontend_remove_save_callback(
|
||||
obs_frontend_save_cb callback, void *private_data)=0;
|
||||
|
||||
virtual void obs_frontend_push_ui_translation(
|
||||
obs_frontend_translate_ui_cb translate)=0;
|
||||
virtual void obs_frontend_pop_ui_translation(void)=0;
|
||||
|
||||
virtual void on_load(obs_data_t *settings)=0;
|
||||
virtual void on_save(obs_data_t *settings)=0;
|
||||
virtual void on_event(enum obs_frontend_event event)=0;
|
||||
};
|
||||
|
||||
EXPORT void obs_frontend_set_callbacks_internal(
|
||||
obs_frontend_callbacks *callbacks);
|
@ -239,6 +239,11 @@ bool OBSBasic::AddProfile(bool create_new, const char *title, const char *text,
|
||||
|
||||
config_save_safe(App()->GlobalConfig(), "tmp", nullptr);
|
||||
UpdateTitleBar();
|
||||
|
||||
if (api) {
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED);
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_CHANGED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -363,6 +368,11 @@ void OBSBasic::on_actionRenameProfile_triggered()
|
||||
DeleteProfile(curName.c_str(), curDir.c_str());
|
||||
RefreshProfiles();
|
||||
}
|
||||
|
||||
if (api) {
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED);
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::on_actionRemoveProfile_triggered()
|
||||
@ -431,6 +441,11 @@ void OBSBasic::on_actionRemoveProfile_triggered()
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
||||
if (api) {
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED);
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::ChangeProfile()
|
||||
@ -481,4 +496,7 @@ void OBSBasic::ChangeProfile()
|
||||
blog(LOG_INFO, "Switched to profile '%s' (%s)",
|
||||
newName, newDir);
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_PROFILE_CHANGED);
|
||||
}
|
||||
|
@ -178,6 +178,11 @@ void OBSBasic::AddSceneCollection(bool create_new)
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
||||
if (api) {
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED);
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::RefreshSceneCollections()
|
||||
@ -267,6 +272,11 @@ void OBSBasic::on_actionRenameSceneCollection_triggered()
|
||||
|
||||
UpdateTitleBar();
|
||||
RefreshSceneCollections();
|
||||
|
||||
if (api) {
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED);
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::on_actionRemoveSceneCollection_triggered()
|
||||
@ -330,6 +340,11 @@ void OBSBasic::on_actionRemoveSceneCollection_triggered()
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
||||
if (api) {
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED);
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::ChangeSceneCollection()
|
||||
@ -366,4 +381,7 @@ void OBSBasic::ChangeSceneCollection()
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED);
|
||||
}
|
||||
|
@ -234,6 +234,9 @@ void OBSBasic::TransitionStopped()
|
||||
SetCurrentScene(scene);
|
||||
}
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_STOPPED);
|
||||
|
||||
swapScene = nullptr;
|
||||
}
|
||||
|
||||
@ -281,6 +284,9 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force)
|
||||
obs_scene_release(scene);
|
||||
|
||||
obs_source_release(transition);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_CHANGED);
|
||||
}
|
||||
|
||||
static inline void SetComboTransition(QComboBox *combo, obs_source_t *tr)
|
||||
@ -317,6 +323,9 @@ void OBSBasic::SetTransition(OBSSource transition)
|
||||
bool configurable = obs_source_configurable(transition);
|
||||
ui->transitionRemove->setEnabled(configurable);
|
||||
ui->transitionProps->setEnabled(configurable);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_CHANGED);
|
||||
}
|
||||
|
||||
OBSSource OBSBasic::GetCurrentTransition()
|
||||
@ -378,6 +387,9 @@ void OBSBasic::AddTransition()
|
||||
ui->transitions->setCurrentIndex(ui->transitions->count() - 1);
|
||||
CreatePropertiesWindow(source);
|
||||
obs_source_release(source);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,6 +440,9 @@ void OBSBasic::on_transitionRemove_clicked()
|
||||
}
|
||||
|
||||
ui->transitions->removeItem(idx);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
|
||||
}
|
||||
|
||||
void OBSBasic::RenameTransition()
|
||||
|
@ -373,6 +373,13 @@ void OBSBasic::Save(const char *file)
|
||||
|
||||
obs_data_set_bool(saveData, "preview_locked", ui->preview->Locked());
|
||||
|
||||
if (api) {
|
||||
obs_data_t *moduleObj = obs_data_create();
|
||||
api->on_save(moduleObj);
|
||||
obs_data_set_obj(saveData, "modules", moduleObj);
|
||||
obs_data_release(moduleObj);
|
||||
}
|
||||
|
||||
if (!obs_data_save_json_safe(saveData, file, "tmp", "bak"))
|
||||
blog(LOG_ERROR, "Could not save scene data to %s", file);
|
||||
|
||||
@ -655,6 +662,12 @@ retryScene:
|
||||
ui->preview->SetLocked(previewLocked);
|
||||
ui->actionLockPreview->setChecked(previewLocked);
|
||||
|
||||
if (api) {
|
||||
obs_data_t *modulesObj = obs_data_get_obj(data, "modules");
|
||||
api->on_load(modulesObj);
|
||||
obs_data_release(modulesObj);
|
||||
}
|
||||
|
||||
obs_data_release(data);
|
||||
|
||||
if (!opt_starting_scene.empty())
|
||||
@ -1019,6 +1032,8 @@ void OBSBasic::ResetOutputs()
|
||||
#define SHUTDOWN_SEPARATOR \
|
||||
"==== Shutting down =================================================="
|
||||
|
||||
extern obs_frontend_callbacks *InitializeAPIInterface(OBSBasic *main);
|
||||
|
||||
void OBSBasic::OBSInit()
|
||||
{
|
||||
ProfileScope("OBSBasic::OBSInit");
|
||||
@ -1065,6 +1080,8 @@ void OBSBasic::OBSInit()
|
||||
InitOBSCallbacks();
|
||||
InitHotkeys();
|
||||
|
||||
api = InitializeAPIInterface(this);
|
||||
|
||||
AddExtraModulePaths();
|
||||
blog(LOG_INFO, "---------------------------------");
|
||||
obs_load_all_modules();
|
||||
@ -2067,6 +2084,9 @@ void OBSBasic::DuplicateSelectedScene()
|
||||
AddScene(source);
|
||||
SetCurrentScene(source, true);
|
||||
obs_scene_release(scene);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2076,8 +2096,12 @@ void OBSBasic::RemoveSelectedScene()
|
||||
OBSScene scene = GetCurrentScene();
|
||||
if (scene) {
|
||||
obs_source_t *source = obs_scene_get_source(scene);
|
||||
if (QueryRemoveSource(source))
|
||||
if (QueryRemoveSource(source)) {
|
||||
obs_source_remove(source);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2639,6 +2663,10 @@ void OBSBasic::closeEvent(QCloseEvent *event)
|
||||
signalHandlers.clear();
|
||||
|
||||
SaveProjectNow();
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_EXIT);
|
||||
|
||||
disableSaving++;
|
||||
|
||||
/* Clear all scene data (dialogs, widgets, widget sub-items, scenes,
|
||||
@ -3487,6 +3515,9 @@ void OBSBasic::SceneNameEdited(QWidget *editor,
|
||||
obs_source_t *source = obs_scene_get_source(scene);
|
||||
RenameListItem(this, ui->scenes, source, text);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED);
|
||||
|
||||
UNUSED_PARAMETER(endHint);
|
||||
}
|
||||
|
||||
@ -3537,6 +3568,12 @@ void OBSBasic::OpenSceneFilters()
|
||||
|
||||
void OBSBasic::StartStreaming()
|
||||
{
|
||||
if (outputHandler->StreamingActive())
|
||||
return;
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_STREAMING_STARTING);
|
||||
|
||||
SaveProject();
|
||||
|
||||
ui->streamButton->setEnabled(false);
|
||||
@ -3684,6 +3721,9 @@ void OBSBasic::StreamingStart()
|
||||
sysTrayStream->setText(ui->streamButton->text());
|
||||
sysTrayStream->setEnabled(true);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_STREAMING_STARTED);
|
||||
|
||||
OnActivate();
|
||||
|
||||
blog(LOG_INFO, STREAMING_START);
|
||||
@ -3693,6 +3733,9 @@ void OBSBasic::StreamStopping()
|
||||
{
|
||||
ui->streamButton->setText(QTStr("Basic.Main.StoppingStreaming"));
|
||||
sysTrayStream->setText(ui->streamButton->text());
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_STREAMING_STOPPING);
|
||||
}
|
||||
|
||||
void OBSBasic::StreamingStop(int code)
|
||||
@ -3730,6 +3773,9 @@ void OBSBasic::StreamingStop(int code)
|
||||
sysTrayStream->setText(ui->streamButton->text());
|
||||
sysTrayStream->setEnabled(true);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_STREAMING_STOPPED);
|
||||
|
||||
OnDeactivate();
|
||||
|
||||
blog(LOG_INFO, STREAMING_STOP);
|
||||
@ -3754,6 +3800,9 @@ void OBSBasic::StartRecording()
|
||||
if (outputHandler->RecordingActive())
|
||||
return;
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STARTING);
|
||||
|
||||
SaveProject();
|
||||
outputHandler->StartRecording();
|
||||
}
|
||||
@ -3762,6 +3811,9 @@ void OBSBasic::RecordStopping()
|
||||
{
|
||||
ui->recordButton->setText(QTStr("Basic.Main.StoppingRecording"));
|
||||
sysTrayRecord->setText(ui->recordButton->text());
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STOPPING);
|
||||
}
|
||||
|
||||
void OBSBasic::StopRecording()
|
||||
@ -3780,6 +3832,9 @@ void OBSBasic::RecordingStart()
|
||||
ui->recordButton->setText(QTStr("Basic.Main.StopRecording"));
|
||||
sysTrayRecord->setText(ui->recordButton->text());
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STARTED);
|
||||
|
||||
OnActivate();
|
||||
|
||||
blog(LOG_INFO, RECORDING_START);
|
||||
@ -3820,6 +3875,9 @@ void OBSBasic::RecordingStop(int code)
|
||||
QSystemTrayIcon::Warning);
|
||||
}
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STOPPED);
|
||||
|
||||
OnDeactivate();
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "window-basic-adv-audio.hpp"
|
||||
#include "window-basic-filters.hpp"
|
||||
|
||||
#include <obs-frontend-internal.hpp>
|
||||
|
||||
#include <util/platform.h>
|
||||
#include <util/threading.h>
|
||||
#include <util/util.hpp>
|
||||
@ -83,6 +85,7 @@ class OBSBasic : public OBSMainWindow {
|
||||
friend class OBSBasicPreview;
|
||||
friend class OBSBasicStatusBar;
|
||||
friend class OBSBasicSourceSelect;
|
||||
friend struct OBSStudioAPI;
|
||||
|
||||
enum class MoveDir {
|
||||
Up,
|
||||
@ -92,6 +95,8 @@ class OBSBasic : public OBSMainWindow {
|
||||
};
|
||||
|
||||
private:
|
||||
obs_frontend_callbacks *api = nullptr;
|
||||
|
||||
std::vector<VolControl*> volumes;
|
||||
|
||||
std::vector<OBSSignal> signalHandlers;
|
||||
|
Loading…
x
Reference in New Issue
Block a user