Files
obs-studio/UI/frontend-plugins/frontend-tools/output-timer.cpp
Ryan Foster 589495a952 frontend-tools: Fix output timer stopping recording on unpause
If the "Pause timer when recording is paused" option in the Output Timer
settings was enabled, even if an Output Timer was not being used, a
recording may stop when attempting to unpause it. This was due to the
check in the UnpauseRecordingTimer function being too loose and only
checking for if the recording timer was not active. Let's initialize the
recordingTimeLeft variable to -1 and check that it's greater than 0
before attempting to restart a recording timer.
2024-03-08 19:18:41 -05:00

351 lines
9.2 KiB
C++

#include <obs-frontend-api.h>
#include <obs-module.h>
#include <obs.hpp>
#include <util/util.hpp>
#include <QAction>
#include <QMainWindow>
#include <QTimer>
#include <QObject>
#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);
}