decklink-captions.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include <obs-frontend-api.h>
  2. #include <QMainWindow>
  3. #include <QAction>
  4. #include <obs.hpp>
  5. #include "decklink-captions.h"
  6. OBS_DECLARE_MODULE()
  7. OBS_MODULE_USE_DEFAULT_LOCALE("decklink-captons", "en-US")
  8. struct obs_captions {
  9. std::string source_name;
  10. OBSWeakSource source;
  11. void start();
  12. void stop();
  13. obs_captions();
  14. inline ~obs_captions() { stop(); }
  15. };
  16. obs_captions::obs_captions() {}
  17. static obs_captions *captions = nullptr;
  18. DecklinkCaptionsUI::DecklinkCaptionsUI(QWidget *parent)
  19. : QDialog(parent),
  20. ui(new Ui_CaptionsDialog)
  21. {
  22. ui->setupUi(this);
  23. setSizeGripEnabled(true);
  24. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  25. auto cb = [this](obs_source_t *source) {
  26. uint32_t caps = obs_source_get_output_flags(source);
  27. QString name = obs_source_get_name(source);
  28. if (caps & OBS_SOURCE_CEA_708)
  29. ui->source->addItem(name);
  30. OBSWeakSource weak = OBSGetWeakRef(source);
  31. if (weak == captions->source)
  32. ui->source->setCurrentText(name);
  33. return true;
  34. };
  35. using cb_t = decltype(cb);
  36. ui->source->blockSignals(true);
  37. ui->source->addItem(QStringLiteral(""));
  38. ui->source->setCurrentIndex(0);
  39. obs_enum_sources(
  40. [](void *data, obs_source_t *source) {
  41. return (*static_cast<cb_t *>(data))(source);
  42. },
  43. &cb);
  44. ui->source->blockSignals(false);
  45. }
  46. void DecklinkCaptionsUI::on_source_currentIndexChanged(int)
  47. {
  48. captions->stop();
  49. captions->source_name = ui->source->currentText().toUtf8().constData();
  50. captions->source = GetWeakSourceByName(captions->source_name.c_str());
  51. captions->start();
  52. }
  53. static void caption_callback(void * /* param */, obs_source_t * /* source */,
  54. const struct obs_source_cea_708 *captions)
  55. {
  56. obs_output *output = obs_frontend_get_streaming_output();
  57. if (output) {
  58. if (obs_frontend_streaming_active() &&
  59. obs_output_active(output)) {
  60. obs_output_caption(output, captions);
  61. }
  62. obs_output_release(output);
  63. }
  64. }
  65. void obs_captions::start()
  66. {
  67. OBSSource s = OBSGetStrongRef(source);
  68. if (!s) {
  69. //warn("Source invalid");
  70. return;
  71. }
  72. obs_source_add_caption_callback(s, caption_callback, nullptr);
  73. }
  74. void obs_captions::stop()
  75. {
  76. OBSSource s = OBSGetStrongRef(source);
  77. if (s)
  78. obs_source_remove_caption_callback(s, caption_callback,
  79. nullptr);
  80. }
  81. static void save_decklink_caption_data(obs_data_t *save_data, bool saving,
  82. void *)
  83. {
  84. if (saving) {
  85. obs_data_t *obj = obs_data_create();
  86. obs_data_set_string(obj, "source",
  87. captions->source_name.c_str());
  88. obs_data_set_obj(save_data, "decklink_captions", obj);
  89. obs_data_release(obj);
  90. } else {
  91. captions->stop();
  92. obs_data_t *obj =
  93. obs_data_get_obj(save_data, "decklink_captions");
  94. if (!obj)
  95. obj = obs_data_create();
  96. captions->source_name = obs_data_get_string(obj, "source");
  97. captions->source =
  98. GetWeakSourceByName(captions->source_name.c_str());
  99. obs_data_release(obj);
  100. captions->start();
  101. }
  102. }
  103. void addOutputUI(void)
  104. {
  105. QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
  106. obs_module_text("Decklink Captions"));
  107. captions = new obs_captions;
  108. auto cb = []() {
  109. obs_frontend_push_ui_translation(obs_module_get_string);
  110. QWidget *window = (QWidget *)obs_frontend_get_main_window();
  111. DecklinkCaptionsUI dialog(window);
  112. dialog.exec();
  113. obs_frontend_pop_ui_translation();
  114. };
  115. obs_frontend_add_save_callback(save_decklink_caption_data, nullptr);
  116. action->connect(action, &QAction::triggered, cb);
  117. }
  118. bool obs_module_load(void)
  119. {
  120. return true;
  121. }
  122. void obs_module_post_load(void)
  123. {
  124. if (!obs_get_module("decklink"))
  125. return;
  126. addOutputUI();
  127. }