decklink-captions.cpp 3.4 KB

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