output-timer.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include <obs-frontend-api.h>
  2. #include <obs-module.h>
  3. #include <obs.hpp>
  4. #include <util/util.hpp>
  5. #include <QAction>
  6. #include <QMainWindow>
  7. #include <QTimer>
  8. #include <QObject>
  9. #include "output-timer.hpp"
  10. using namespace std;
  11. OutputTimer *ot;
  12. OutputTimer::OutputTimer(QWidget *parent) : QDialog(parent), ui(new Ui_OutputTimer)
  13. {
  14. ui->setupUi(this);
  15. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  16. QObject::connect(ui->outputTimerStream, &QPushButton::clicked, this, &OutputTimer::StreamingTimerButton);
  17. QObject::connect(ui->outputTimerRecord, &QPushButton::clicked, this, &OutputTimer::RecordingTimerButton);
  18. QObject::connect(ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this,
  19. &OutputTimer::hide);
  20. streamingTimer = new QTimer(this);
  21. streamingTimerDisplay = new QTimer(this);
  22. recordingTimer = new QTimer(this);
  23. recordingTimerDisplay = new QTimer(this);
  24. QObject::connect(streamingTimer, &QTimer::timeout, this, &OutputTimer::EventStopStreaming);
  25. QObject::connect(streamingTimerDisplay, &QTimer::timeout, this, &OutputTimer::UpdateStreamTimerDisplay);
  26. QObject::connect(recordingTimer, &QTimer::timeout, this, &OutputTimer::EventStopRecording);
  27. QObject::connect(recordingTimerDisplay, &QTimer::timeout, this, &OutputTimer::UpdateRecordTimerDisplay);
  28. }
  29. void OutputTimer::closeEvent(QCloseEvent *)
  30. {
  31. obs_frontend_save();
  32. }
  33. void OutputTimer::StreamingTimerButton()
  34. {
  35. if (!obs_frontend_streaming_active()) {
  36. blog(LOG_INFO, "Starting stream due to OutputTimer");
  37. obs_frontend_streaming_start();
  38. } else if (streamingAlreadyActive) {
  39. StreamTimerStart();
  40. streamingAlreadyActive = false;
  41. } else if (obs_frontend_streaming_active()) {
  42. blog(LOG_INFO, "Stopping stream due to OutputTimer");
  43. obs_frontend_streaming_stop();
  44. }
  45. }
  46. void OutputTimer::RecordingTimerButton()
  47. {
  48. if (!obs_frontend_recording_active()) {
  49. blog(LOG_INFO, "Starting recording due to OutputTimer");
  50. obs_frontend_recording_start();
  51. } else if (recordingAlreadyActive) {
  52. RecordTimerStart();
  53. recordingAlreadyActive = false;
  54. } else if (obs_frontend_recording_active()) {
  55. blog(LOG_INFO, "Stopping recording due to OutputTimer");
  56. obs_frontend_recording_stop();
  57. }
  58. }
  59. void OutputTimer::StreamTimerStart()
  60. {
  61. if (!isVisible() && ui->autoStartStreamTimer->isChecked() == false) {
  62. streamingAlreadyActive = true;
  63. return;
  64. }
  65. int hours = ui->streamingTimerHours->value();
  66. int minutes = ui->streamingTimerMinutes->value();
  67. int seconds = ui->streamingTimerSeconds->value();
  68. int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000;
  69. if (total == 0)
  70. total = 1000;
  71. streamingTimer->setInterval(total);
  72. streamingTimer->setSingleShot(true);
  73. streamingTimer->start();
  74. streamingTimerDisplay->start(1000);
  75. ui->outputTimerStream->setText(obs_module_text("Stop"));
  76. UpdateStreamTimerDisplay();
  77. ui->outputTimerStream->setChecked(true);
  78. }
  79. void OutputTimer::RecordTimerStart()
  80. {
  81. if (!isVisible() && ui->autoStartRecordTimer->isChecked() == false) {
  82. recordingAlreadyActive = true;
  83. return;
  84. }
  85. int hours = ui->recordingTimerHours->value();
  86. int minutes = ui->recordingTimerMinutes->value();
  87. int seconds = ui->recordingTimerSeconds->value();
  88. int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000;
  89. if (total == 0)
  90. total = 1000;
  91. recordingTimer->setInterval(total);
  92. recordingTimer->setSingleShot(true);
  93. recordingTimer->start();
  94. recordingTimerDisplay->start(1000);
  95. ui->outputTimerRecord->setText(obs_module_text("Stop"));
  96. UpdateRecordTimerDisplay();
  97. ui->outputTimerRecord->setChecked(true);
  98. }
  99. void OutputTimer::StreamTimerStop()
  100. {
  101. streamingAlreadyActive = false;
  102. if (!isVisible() && streamingTimer->isActive() == false)
  103. return;
  104. if (streamingTimer->isActive())
  105. streamingTimer->stop();
  106. ui->outputTimerStream->setText(obs_module_text("Start"));
  107. if (streamingTimerDisplay->isActive())
  108. streamingTimerDisplay->stop();
  109. ui->streamTime->setText("00:00:00");
  110. ui->outputTimerStream->setChecked(false);
  111. }
  112. void OutputTimer::RecordTimerStop()
  113. {
  114. recordingAlreadyActive = false;
  115. if (!isVisible() && recordingTimer->isActive() == false)
  116. return;
  117. if (recordingTimer->isActive())
  118. recordingTimer->stop();
  119. ui->outputTimerRecord->setText(obs_module_text("Start"));
  120. if (recordingTimerDisplay->isActive())
  121. recordingTimerDisplay->stop();
  122. ui->recordTime->setText("00:00:00");
  123. ui->outputTimerRecord->setChecked(false);
  124. }
  125. void OutputTimer::UpdateStreamTimerDisplay()
  126. {
  127. int remainingTime = streamingTimer->remainingTime() / 1000;
  128. int seconds = remainingTime % 60;
  129. int minutes = (remainingTime % 3600) / 60;
  130. int hours = remainingTime / 3600;
  131. QString text = QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
  132. ui->streamTime->setText(text);
  133. }
  134. void OutputTimer::UpdateRecordTimerDisplay()
  135. {
  136. int remainingTime = 0;
  137. if (obs_frontend_recording_paused() && ui->pauseRecordTimer->isChecked())
  138. remainingTime = recordingTimeLeft / 1000;
  139. else
  140. remainingTime = recordingTimer->remainingTime() / 1000;
  141. int seconds = remainingTime % 60;
  142. int minutes = (remainingTime % 3600) / 60;
  143. int hours = remainingTime / 3600;
  144. QString text = QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
  145. ui->recordTime->setText(text);
  146. }
  147. void OutputTimer::PauseRecordingTimer()
  148. {
  149. if (!ui->pauseRecordTimer->isChecked())
  150. return;
  151. if (recordingTimer->isActive()) {
  152. recordingTimeLeft = recordingTimer->remainingTime();
  153. recordingTimer->stop();
  154. }
  155. }
  156. void OutputTimer::UnpauseRecordingTimer()
  157. {
  158. if (!ui->pauseRecordTimer->isChecked())
  159. return;
  160. if (recordingTimeLeft > 0 && !recordingTimer->isActive())
  161. recordingTimer->start(recordingTimeLeft);
  162. }
  163. void OutputTimer::ShowHideDialog()
  164. {
  165. if (!isVisible()) {
  166. setVisible(true);
  167. QTimer::singleShot(250, this, &OutputTimer::show);
  168. } else {
  169. setVisible(false);
  170. QTimer::singleShot(250, this, &OutputTimer::hide);
  171. }
  172. }
  173. void OutputTimer::EventStopStreaming()
  174. {
  175. blog(LOG_INFO, "Stopping stream due to OutputTimer timeout");
  176. obs_frontend_streaming_stop();
  177. }
  178. void OutputTimer::EventStopRecording()
  179. {
  180. blog(LOG_INFO, "Stopping recording due to OutputTimer timeout");
  181. obs_frontend_recording_stop();
  182. }
  183. static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *)
  184. {
  185. if (saving) {
  186. OBSDataAutoRelease obj = obs_data_create();
  187. obs_data_set_int(obj, "streamTimerHours", ot->ui->streamingTimerHours->value());
  188. obs_data_set_int(obj, "streamTimerMinutes", ot->ui->streamingTimerMinutes->value());
  189. obs_data_set_int(obj, "streamTimerSeconds", ot->ui->streamingTimerSeconds->value());
  190. obs_data_set_int(obj, "recordTimerHours", ot->ui->recordingTimerHours->value());
  191. obs_data_set_int(obj, "recordTimerMinutes", ot->ui->recordingTimerMinutes->value());
  192. obs_data_set_int(obj, "recordTimerSeconds", ot->ui->recordingTimerSeconds->value());
  193. obs_data_set_bool(obj, "autoStartStreamTimer", ot->ui->autoStartStreamTimer->isChecked());
  194. obs_data_set_bool(obj, "autoStartRecordTimer", ot->ui->autoStartRecordTimer->isChecked());
  195. obs_data_set_bool(obj, "pauseRecordTimer", ot->ui->pauseRecordTimer->isChecked());
  196. obs_data_set_obj(save_data, "output-timer", obj);
  197. } else {
  198. OBSDataAutoRelease obj = obs_data_get_obj(save_data, "output-timer");
  199. if (!obj)
  200. obj = obs_data_create();
  201. ot->ui->streamingTimerHours->setValue(obs_data_get_int(obj, "streamTimerHours"));
  202. ot->ui->streamingTimerMinutes->setValue(obs_data_get_int(obj, "streamTimerMinutes"));
  203. ot->ui->streamingTimerSeconds->setValue(obs_data_get_int(obj, "streamTimerSeconds"));
  204. ot->ui->recordingTimerHours->setValue(obs_data_get_int(obj, "recordTimerHours"));
  205. ot->ui->recordingTimerMinutes->setValue(obs_data_get_int(obj, "recordTimerMinutes"));
  206. ot->ui->recordingTimerSeconds->setValue(obs_data_get_int(obj, "recordTimerSeconds"));
  207. ot->ui->autoStartStreamTimer->setChecked(obs_data_get_bool(obj, "autoStartStreamTimer"));
  208. ot->ui->autoStartRecordTimer->setChecked(obs_data_get_bool(obj, "autoStartRecordTimer"));
  209. ot->ui->pauseRecordTimer->setChecked(obs_data_get_bool(obj, "pauseRecordTimer"));
  210. }
  211. }
  212. extern "C" void FreeOutputTimer() {}
  213. static void OBSEvent(enum obs_frontend_event event, void *)
  214. {
  215. if (event == OBS_FRONTEND_EVENT_EXIT) {
  216. obs_frontend_save();
  217. FreeOutputTimer();
  218. } else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) {
  219. ot->StreamTimerStart();
  220. } else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPING) {
  221. ot->StreamTimerStop();
  222. } else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) {
  223. ot->RecordTimerStart();
  224. } else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPING) {
  225. ot->RecordTimerStop();
  226. } else if (event == OBS_FRONTEND_EVENT_RECORDING_PAUSED) {
  227. ot->PauseRecordingTimer();
  228. } else if (event == OBS_FRONTEND_EVENT_RECORDING_UNPAUSED) {
  229. ot->UnpauseRecordingTimer();
  230. }
  231. }
  232. extern "C" void InitOutputTimer()
  233. {
  234. QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("OutputTimer"));
  235. obs_frontend_push_ui_translation(obs_module_get_string);
  236. QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window();
  237. ot = new OutputTimer(window);
  238. auto cb = []() {
  239. ot->ShowHideDialog();
  240. };
  241. obs_frontend_pop_ui_translation();
  242. obs_frontend_add_save_callback(SaveOutputTimer, nullptr);
  243. obs_frontend_add_event_callback(OBSEvent, nullptr);
  244. action->connect(action, &QAction::triggered, cb);
  245. }