#include #include #include #include #include #include #include #include #include "output-timer.hpp" using namespace std; OutputTimer *ot; OutputTimer::OutputTimer(QWidget *parent) : QDialog(parent), ui(new Ui_OutputTimer) { ui->setupUi(this); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); QObject::connect(ui->outputTimerStream, &QPushButton::clicked, this, &OutputTimer::StreamingTimerButton); QObject::connect(ui->outputTimerRecord, &QPushButton::clicked, this, &OutputTimer::RecordingTimerButton); QObject::connect(ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &OutputTimer::hide); streamingTimer = new QTimer(this); streamingTimerDisplay = new QTimer(this); recordingTimer = new QTimer(this); recordingTimerDisplay = new QTimer(this); QObject::connect(streamingTimer, &QTimer::timeout, this, &OutputTimer::EventStopStreaming); QObject::connect(streamingTimerDisplay, &QTimer::timeout, this, &OutputTimer::UpdateStreamTimerDisplay); QObject::connect(recordingTimer, &QTimer::timeout, this, &OutputTimer::EventStopRecording); QObject::connect(recordingTimerDisplay, &QTimer::timeout, this, &OutputTimer::UpdateRecordTimerDisplay); } void OutputTimer::closeEvent(QCloseEvent *) { obs_frontend_save(); } void OutputTimer::StreamingTimerButton() { if (!obs_frontend_streaming_active()) { blog(LOG_INFO, "Starting stream due to OutputTimer"); obs_frontend_streaming_start(); } else if (streamingAlreadyActive) { StreamTimerStart(); streamingAlreadyActive = false; } else if (obs_frontend_streaming_active()) { blog(LOG_INFO, "Stopping stream due to OutputTimer"); obs_frontend_streaming_stop(); } } void OutputTimer::RecordingTimerButton() { if (!obs_frontend_recording_active()) { blog(LOG_INFO, "Starting recording due to OutputTimer"); obs_frontend_recording_start(); } else if (recordingAlreadyActive) { RecordTimerStart(); recordingAlreadyActive = false; } else if (obs_frontend_recording_active()) { blog(LOG_INFO, "Stopping recording due to OutputTimer"); obs_frontend_recording_stop(); } } void OutputTimer::StreamTimerStart() { if (!isVisible() && ui->autoStartStreamTimer->isChecked() == false) { streamingAlreadyActive = true; return; } int hours = ui->streamingTimerHours->value(); int minutes = ui->streamingTimerMinutes->value(); int seconds = ui->streamingTimerSeconds->value(); int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000; if (total == 0) total = 1000; streamingTimer->setInterval(total); streamingTimer->setSingleShot(true); streamingTimer->start(); streamingTimerDisplay->start(1000); ui->outputTimerStream->setText(obs_module_text("Stop")); UpdateStreamTimerDisplay(); ui->outputTimerStream->setChecked(true); } void OutputTimer::RecordTimerStart() { if (!isVisible() && ui->autoStartRecordTimer->isChecked() == false) { recordingAlreadyActive = true; return; } int hours = ui->recordingTimerHours->value(); int minutes = ui->recordingTimerMinutes->value(); int seconds = ui->recordingTimerSeconds->value(); int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000; if (total == 0) total = 1000; recordingTimer->setInterval(total); recordingTimer->setSingleShot(true); recordingTimer->start(); recordingTimerDisplay->start(1000); ui->outputTimerRecord->setText(obs_module_text("Stop")); UpdateRecordTimerDisplay(); ui->outputTimerRecord->setChecked(true); } void OutputTimer::StreamTimerStop() { streamingAlreadyActive = false; if (!isVisible() && streamingTimer->isActive() == false) return; if (streamingTimer->isActive()) streamingTimer->stop(); ui->outputTimerStream->setText(obs_module_text("Start")); if (streamingTimerDisplay->isActive()) streamingTimerDisplay->stop(); ui->streamTime->setText("00:00:00"); ui->outputTimerStream->setChecked(false); } void OutputTimer::RecordTimerStop() { recordingAlreadyActive = false; if (!isVisible() && recordingTimer->isActive() == false) return; if (recordingTimer->isActive()) recordingTimer->stop(); ui->outputTimerRecord->setText(obs_module_text("Start")); if (recordingTimerDisplay->isActive()) recordingTimerDisplay->stop(); ui->recordTime->setText("00:00:00"); ui->outputTimerRecord->setChecked(false); } void OutputTimer::UpdateStreamTimerDisplay() { int remainingTime = streamingTimer->remainingTime() / 1000; int seconds = remainingTime % 60; int minutes = (remainingTime % 3600) / 60; int hours = remainingTime / 3600; QString text = QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds); ui->streamTime->setText(text); } void OutputTimer::UpdateRecordTimerDisplay() { int remainingTime = 0; if (obs_frontend_recording_paused() && ui->pauseRecordTimer->isChecked()) remainingTime = recordingTimeLeft / 1000; else remainingTime = recordingTimer->remainingTime() / 1000; int seconds = remainingTime % 60; int minutes = (remainingTime % 3600) / 60; int hours = remainingTime / 3600; QString text = QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds); ui->recordTime->setText(text); } void OutputTimer::PauseRecordingTimer() { if (!ui->pauseRecordTimer->isChecked()) return; if (recordingTimer->isActive()) { recordingTimeLeft = recordingTimer->remainingTime(); recordingTimer->stop(); } } void OutputTimer::UnpauseRecordingTimer() { if (!ui->pauseRecordTimer->isChecked()) return; if (recordingTimeLeft > 0 && !recordingTimer->isActive()) recordingTimer->start(recordingTimeLeft); } void OutputTimer::ShowHideDialog() { if (!isVisible()) { setVisible(true); QTimer::singleShot(250, this, &OutputTimer::show); } else { setVisible(false); QTimer::singleShot(250, this, &OutputTimer::hide); } } void OutputTimer::EventStopStreaming() { blog(LOG_INFO, "Stopping stream due to OutputTimer timeout"); obs_frontend_streaming_stop(); } void OutputTimer::EventStopRecording() { blog(LOG_INFO, "Stopping recording due to OutputTimer timeout"); obs_frontend_recording_stop(); } static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *) { if (saving) { OBSDataAutoRelease obj = obs_data_create(); obs_data_set_int(obj, "streamTimerHours", ot->ui->streamingTimerHours->value()); obs_data_set_int(obj, "streamTimerMinutes", ot->ui->streamingTimerMinutes->value()); obs_data_set_int(obj, "streamTimerSeconds", ot->ui->streamingTimerSeconds->value()); obs_data_set_int(obj, "recordTimerHours", ot->ui->recordingTimerHours->value()); obs_data_set_int(obj, "recordTimerMinutes", ot->ui->recordingTimerMinutes->value()); obs_data_set_int(obj, "recordTimerSeconds", ot->ui->recordingTimerSeconds->value()); obs_data_set_bool(obj, "autoStartStreamTimer", ot->ui->autoStartStreamTimer->isChecked()); obs_data_set_bool(obj, "autoStartRecordTimer", ot->ui->autoStartRecordTimer->isChecked()); obs_data_set_bool(obj, "pauseRecordTimer", ot->ui->pauseRecordTimer->isChecked()); obs_data_set_obj(save_data, "output-timer", obj); } else { OBSDataAutoRelease obj = obs_data_get_obj(save_data, "output-timer"); if (!obj) obj = obs_data_create(); ot->ui->streamingTimerHours->setValue( obs_data_get_int(obj, "streamTimerHours")); ot->ui->streamingTimerMinutes->setValue( obs_data_get_int(obj, "streamTimerMinutes")); ot->ui->streamingTimerSeconds->setValue( obs_data_get_int(obj, "streamTimerSeconds")); ot->ui->recordingTimerHours->setValue( obs_data_get_int(obj, "recordTimerHours")); ot->ui->recordingTimerMinutes->setValue( obs_data_get_int(obj, "recordTimerMinutes")); ot->ui->recordingTimerSeconds->setValue( obs_data_get_int(obj, "recordTimerSeconds")); ot->ui->autoStartStreamTimer->setChecked( obs_data_get_bool(obj, "autoStartStreamTimer")); ot->ui->autoStartRecordTimer->setChecked( obs_data_get_bool(obj, "autoStartRecordTimer")); ot->ui->pauseRecordTimer->setChecked( obs_data_get_bool(obj, "pauseRecordTimer")); } } extern "C" void FreeOutputTimer() {} static void OBSEvent(enum obs_frontend_event event, void *) { if (event == OBS_FRONTEND_EVENT_EXIT) { obs_frontend_save(); FreeOutputTimer(); } else if (event == OBS_FRONTEND_EVENT_STREAMING_STARTED) { ot->StreamTimerStart(); } else if (event == OBS_FRONTEND_EVENT_STREAMING_STOPPING) { ot->StreamTimerStop(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_STARTED) { ot->RecordTimerStart(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_STOPPING) { ot->RecordTimerStop(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_PAUSED) { ot->PauseRecordingTimer(); } else if (event == OBS_FRONTEND_EVENT_RECORDING_UNPAUSED) { ot->UnpauseRecordingTimer(); } } extern "C" void InitOutputTimer() { QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction( obs_module_text("OutputTimer")); obs_frontend_push_ui_translation(obs_module_get_string); QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window(); ot = new OutputTimer(window); auto cb = []() { ot->ShowHideDialog(); }; obs_frontend_pop_ui_translation(); obs_frontend_add_save_callback(SaveOutputTimer, nullptr); obs_frontend_add_event_callback(OBSEvent, nullptr); action->connect(action, &QAction::triggered, cb); }