Files
obs-studio/plugins/decklink-captions/decklink-captions.cpp
PatTheMav 1829492e6b cmake: Move frontend plugins into main plugins dir
Frontend plugins should not require being placed in the frontend
directory to be built successfully. Indeed they should only depend
on libobs and the obs-frontend-api and thus their source tree should
be able to exist anywhere (even standalone) and the plugin should still
compile successfully (just like any 3rd party plugin).

Thus moving those plugins into the main plugin directory ensures that
they don't require on any "special sauce" within the source tree to
compile.
2026-06-05 16:00:18 -04:00

151 lines
3.4 KiB
C++

#include <obs-frontend-api.h>
#include <QMainWindow>
#include <QAction>
#include <obs.hpp>
#include "decklink-captions.h"
OBS_DECLARE_MODULE()
OBS_MODULE_USE_DEFAULT_LOCALE("decklink-captons", "en-US")
struct obs_captions {
std::string source_name;
OBSWeakSource source;
void start();
void stop();
obs_captions();
inline ~obs_captions() { stop(); }
};
obs_captions::obs_captions() {}
static obs_captions *captions = nullptr;
DecklinkCaptionsUI::DecklinkCaptionsUI(QWidget *parent) : QDialog(parent), ui(new Ui_CaptionsDialog)
{
ui->setupUi(this);
setSizeGripEnabled(true);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
auto cb = [this](obs_source_t *source) {
uint32_t caps = obs_source_get_output_flags(source);
QString name = obs_source_get_name(source);
if (caps & OBS_SOURCE_CEA_708)
ui->source->addItem(name);
OBSWeakSource weak = OBSGetWeakRef(source);
if (weak == captions->source)
ui->source->setCurrentText(name);
return true;
};
using cb_t = decltype(cb);
ui->source->blockSignals(true);
ui->source->addItem(QStringLiteral(""));
ui->source->setCurrentIndex(0);
obs_enum_sources([](void *data, obs_source_t *source) { return (*static_cast<cb_t *>(data))(source); }, &cb);
ui->source->blockSignals(false);
}
void DecklinkCaptionsUI::on_source_currentIndexChanged(int)
{
captions->stop();
captions->source_name = ui->source->currentText().toUtf8().constData();
captions->source = GetWeakSourceByName(captions->source_name.c_str());
captions->start();
}
static void caption_callback(void * /* param */, obs_source_t * /* source */, const struct obs_source_cea_708 *captions)
{
obs_output *output = obs_frontend_get_streaming_output();
if (output) {
if (obs_frontend_streaming_active() && obs_output_active(output)) {
obs_output_caption(output, captions);
}
obs_output_release(output);
}
}
void obs_captions::start()
{
OBSSource s = OBSGetStrongRef(source);
if (!s) {
//warn("Source invalid");
return;
}
obs_source_add_caption_callback(s, caption_callback, nullptr);
}
void obs_captions::stop()
{
OBSSource s = OBSGetStrongRef(source);
if (s)
obs_source_remove_caption_callback(s, caption_callback, nullptr);
}
static void save_decklink_caption_data(obs_data_t *save_data, bool saving, void *)
{
if (saving) {
obs_data_t *obj = obs_data_create();
obs_data_set_string(obj, "source", captions->source_name.c_str());
obs_data_set_obj(save_data, "decklink_captions", obj);
obs_data_release(obj);
} else {
captions->stop();
obs_data_t *obj = obs_data_get_obj(save_data, "decklink_captions");
if (!obj)
obj = obs_data_create();
captions->source_name = obs_data_get_string(obj, "source");
captions->source = GetWeakSourceByName(captions->source_name.c_str());
obs_data_release(obj);
captions->start();
}
}
void addOutputUI(void)
{
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("Decklink Captions"));
captions = new obs_captions;
auto cb = []() {
obs_frontend_push_ui_translation(obs_module_get_string);
QWidget *window = (QWidget *)obs_frontend_get_main_window();
DecklinkCaptionsUI dialog(window);
dialog.exec();
obs_frontend_pop_ui_translation();
};
obs_frontend_add_save_callback(save_decklink_caption_data, nullptr);
QObject::connect(action, &QAction::triggered, action, cb);
}
bool obs_module_load(void)
{
return true;
}
void obs_module_post_load(void)
{
if (!obs_get_module("decklink"))
return;
addOutputUI();
}