From 7e5c7da542b3c06ca3aa60249aa3a236f6d1e072 Mon Sep 17 00:00:00 2001 From: cg2121 Date: Wed, 21 Sep 2016 03:51:18 -0500 Subject: [PATCH] frontend-tools: Add output timers This adds streaming and recording timers to the frontend tools. Closes jp9000/obs-studio#625 --- UI/data/locale/en-US.ini | 3 + UI/frontend-plugins/CMakeLists.txt | 4 +- .../frontend-tools/CMakeLists.txt | 21 +- .../frontend-tools/data/locale/en-US.ini | 6 + .../frontend-tools/forms/output-timer.ui | 194 ++++++++++ .../frontend-tools/frontend-tools.c | 10 + .../frontend-tools/output-timer.cpp | 339 ++++++++++++++++++ .../frontend-tools/output-timer.hpp | 31 ++ 8 files changed, 602 insertions(+), 6 deletions(-) create mode 100644 UI/frontend-plugins/frontend-tools/forms/output-timer.ui create mode 100644 UI/frontend-plugins/frontend-tools/output-timer.cpp create mode 100644 UI/frontend-plugins/frontend-tools/output-timer.hpp diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 3d6f196b..0b66d438 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -54,6 +54,9 @@ Right="Right" Top="Top" Bottom="Bottom" Reset="Reset" +Hours="Hours" +Minutes="Minutes" +Seconds="Seconds" # quick transitions QuickTransitions.SwapScenes="Swap Preview/Output Scenes After Transitioning" diff --git a/UI/frontend-plugins/CMakeLists.txt b/UI/frontend-plugins/CMakeLists.txt index 0a90a60a..bd2d3368 100644 --- a/UI/frontend-plugins/CMakeLists.txt +++ b/UI/frontend-plugins/CMakeLists.txt @@ -1,3 +1 @@ -if(WIN32 OR APPLE) - add_subdirectory(frontend-tools) -endif() +add_subdirectory(frontend-tools) diff --git a/UI/frontend-plugins/frontend-tools/CMakeLists.txt b/UI/frontend-plugins/frontend-tools/CMakeLists.txt index b15dc525..f186de64 100644 --- a/UI/frontend-plugins/frontend-tools/CMakeLists.txt +++ b/UI/frontend-plugins/frontend-tools/CMakeLists.txt @@ -5,15 +5,30 @@ if(APPLE) include_directories(${COCOA}) endif() +if(WIN32 OR APPLE) + set(frontend-tools_HEADERS + auto-scene-switcher.hpp + ) + set(frontend-tools_SOURCES + auto-scene-switcher.cpp + ) + set(frontend-tools_UI + forms/auto-scene-switcher.ui + ) +endif() + set(frontend-tools_HEADERS - auto-scene-switcher.hpp + ${frontend-tools_HEADERS} + output-timer.hpp ) set(frontend-tools_SOURCES + ${frontend-tools_SOURCES} frontend-tools.c - auto-scene-switcher.cpp + output-timer.cpp ) set(frontend-tools_UI - forms/auto-scene-switcher.ui + ${frontend-tools_UI} + forms/output-timer.ui ) if(WIN32) diff --git a/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini b/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini index 154241d4..08580f39 100644 --- a/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini +++ b/UI/frontend-plugins/frontend-tools/data/locale/en-US.ini @@ -10,3 +10,9 @@ Active="Active" Inactive="Inactive" Start="Start" Stop="Stop" + +OutputTimer="Output Timer" +OutputTimer.Stream="Stop streaming after:" +OutputTimer.Record="Stop recording after:" +OutputTimer.Stream.StoppingIn="Streaming stopping in:" +OutputTimer.Record.StoppingIn="Recording stopping in:" diff --git a/UI/frontend-plugins/frontend-tools/forms/output-timer.ui b/UI/frontend-plugins/frontend-tools/forms/output-timer.ui new file mode 100644 index 00000000..8c983421 --- /dev/null +++ b/UI/frontend-plugins/frontend-tools/forms/output-timer.ui @@ -0,0 +1,194 @@ + + + OutputTimer + + + + 0 + 0 + 600 + 150 + + + + OutputTimer + + + + + + OutputTimer.Stream + + + + + + + 0 + + + 24 + + + 0 + + + + + + + Hours + + + + + + + 59 + + + 0 + + + + + + + Minutes + + + + + + + 0 + + + 59 + + + 30 + + + + + + + Seconds + + + + + + + Start + + + + + + + OutputTimer.Stream.StoppingIn + + + + + + + 00:00:00 + + + + + + + OutputTimer.Record + + + + + + + 0 + + + 24 + + + 0 + + + + + + + Hours + + + + + + + 0 + + + 59 + + + 0 + + + + + + + Minutes + + + + + + + 0 + + + 59 + + + 30 + + + + + + + Seconds + + + + + + + Start + + + + + + + OutputTimer.Record.StoppingIn + + + + + + + 00:00:00 + + + + + + + + diff --git a/UI/frontend-plugins/frontend-tools/frontend-tools.c b/UI/frontend-plugins/frontend-tools/frontend-tools.c index 3826f041..fb92b540 100644 --- a/UI/frontend-plugins/frontend-tools/frontend-tools.c +++ b/UI/frontend-plugins/frontend-tools/frontend-tools.c @@ -3,16 +3,26 @@ OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("frontend-tools", "en-US") +#if defined(_WIN32) || defined(__APPLE__) void InitSceneSwitcher(); void FreeSceneSwitcher(); +#endif +void InitOutputTimer(); +void FreeOutputTimer(); bool obs_module_load(void) { +#if defined(_WIN32) || defined(__APPLE__) InitSceneSwitcher(); +#endif + InitOutputTimer(); return true; } void obs_module_unload(void) { +#if defined(_WIN32) || defined(__APPLE__) FreeSceneSwitcher(); +#endif + FreeOutputTimer(); } diff --git a/UI/frontend-plugins/frontend-tools/output-timer.cpp b/UI/frontend-plugins/frontend-tools/output-timer.cpp new file mode 100644 index 00000000..2ecfae8b --- /dev/null +++ b/UI/frontend-plugins/frontend-tools/output-timer.cpp @@ -0,0 +1,339 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "output-timer.hpp" + +using namespace std; + +struct TimerData { + int streamTimerHours = 0; + int streamTimerMinutes = 0; + int streamTimerSeconds = 0; + int streamTimerTotal = 0; + + int recordTimerHours = 0; + int recordTimerMinutes = 0; + int recordTimerSeconds = 0; + int recordTimerTotal = 0; + + int streamTimerDisplay = 0; + int recordTimerDisplay = 0; + + int secondsStream = 0; + int totalMinutesStream = 0; + int minutesStream = 0; + int hoursStream = 0; + + int secondsRecord = 0; + int totalMinutesRecord = 0; + int minutesRecord = 0; + int hoursRecord = 0; + + bool streamButtonClicked = false; + bool recordButtonClicked = false; + + QTimer *streamingTimer; + QTimer *recordingTimer; + QTimer *streamingTimerDisplay; + QTimer *recordingTimerDisplay; + + QString textStream; + QString textRecord; +}; + +QMainWindow *window; +OutputTimer *ot; + +static TimerData *timer = nullptr; + +OutputTimer::OutputTimer(QWidget *parent) + : QDialog(parent), + ui(new Ui_OutputTimer) +{ + ui->setupUi(this); + + QObject::connect(ui->outputTimerStream, SIGNAL(clicked()), this, + SLOT(StreamingTimerButton())); + QObject::connect(ui->outputTimerRecord, SIGNAL(clicked()), this, + SLOT(RecordingTimerButton())); +} + +void OutputTimer::closeEvent(QCloseEvent*) +{ + obs_frontend_save(); +} + +void OutputTimer::StreamingTimerButton() +{ + if (obs_frontend_streaming_active()) + obs_frontend_streaming_stop(); + else + obs_frontend_streaming_start(); +} + +void OutputTimer::RecordingTimerButton() +{ + if (obs_frontend_recording_active()) + obs_frontend_recording_stop(); + else + obs_frontend_recording_start(); +} + +void OutputTimer::StreamTimerStart() +{ + timer->streamingTimer = new QTimer(this); + timer->streamingTimerDisplay = new QTimer(this); + + if (!isVisible()) { + ui->outputTimerStream->setEnabled(false); + return; + } + + timer->streamTimerHours = ui->streamingTimerHours->value(); + timer->streamTimerMinutes = ui->streamingTimerMinutes->value(); + timer->streamTimerSeconds = ui->streamingTimerSeconds->value(); + + timer->streamTimerTotal = (((timer->streamTimerHours * 3600) + + (timer->streamTimerMinutes * 60)) + + timer->streamTimerSeconds) * 1000; + + if (timer->streamTimerTotal == 0) + timer->streamTimerTotal = 1000; + + timer->streamTimerDisplay = timer->streamTimerTotal / 1000; + + timer->streamingTimer->setInterval(timer->streamTimerTotal); + timer->streamingTimer->setSingleShot(true); + + QObject::connect(timer->streamingTimer, SIGNAL(timeout()), + SLOT(EventStopStreaming())); + + QObject::connect(timer->streamingTimerDisplay, SIGNAL(timeout()), this, + SLOT(UpdateStreamTimerDisplay())); + + timer->streamingTimer->start(); + timer->streamingTimerDisplay->start(1000); + ui->outputTimerStream->setText(tr("Stop")); +} + +void OutputTimer::RecordTimerStart() +{ + timer->recordingTimer = new QTimer(this); + timer->recordingTimerDisplay = new QTimer(this); + + if (!isVisible()) { + ui->outputTimerRecord->setEnabled(false); + return; + } + + timer->recordTimerHours = ui->recordingTimerHours->value(); + timer->recordTimerMinutes = ui->recordingTimerMinutes->value(); + timer->recordTimerSeconds = ui->recordingTimerSeconds->value(); + + timer->recordTimerTotal = (((timer->recordTimerHours * 3600) + + (timer->recordTimerMinutes * 60)) + + timer->recordTimerSeconds) * 1000; + + if (timer->recordTimerTotal == 0) + timer->recordTimerTotal = 1000; + + timer->recordTimerDisplay = timer->recordTimerTotal / 1000; + + timer->recordingTimer->setInterval(timer->recordTimerTotal); + timer->recordingTimer->setSingleShot(true); + + QObject::connect(timer->recordingTimer, SIGNAL(timeout()), + SLOT(EventStopRecording())); + + QObject::connect(timer->recordingTimerDisplay, SIGNAL(timeout()), this, + SLOT(UpdateRecordTimerDisplay())); + + timer->recordingTimer->start(); + timer->recordingTimerDisplay->start(1000); + ui->outputTimerRecord->setText(tr("Stop")); +} + +void OutputTimer::StreamTimerStop() +{ + ui->outputTimerStream->setEnabled(true); + + if (!isVisible() && timer->streamingTimer->isActive() == false) + return; + + if (timer->streamingTimer->isActive()) + timer->streamingTimer->stop(); + + ui->outputTimerStream->setText(tr("Start")); + + if (timer->streamingTimerDisplay->isActive()) + timer->streamingTimerDisplay->stop(); + + ui->streamTime->setText("00:00:00"); +} + +void OutputTimer::RecordTimerStop() +{ + ui->outputTimerRecord->setEnabled(true); + + if (!isVisible() && timer->recordingTimer->isActive() == false) + return; + + if (timer->recordingTimer->isActive()) + timer->recordingTimer->stop(); + + ui->outputTimerRecord->setText(tr("Start")); + + if (timer->recordingTimerDisplay->isActive()) + timer->recordingTimerDisplay->stop(); + + ui->recordTime->setText("00:00:00"); +} + +void OutputTimer::UpdateStreamTimerDisplay() +{ + timer->streamTimerDisplay--; + + timer->secondsStream = timer->streamTimerDisplay % 60; + timer->totalMinutesStream = timer->streamTimerDisplay / 60; + timer->minutesStream = timer->totalMinutesStream % 60; + timer->hoursStream = timer->totalMinutesStream / 60; + + timer->textStream.sprintf("%02d:%02d:%02d", + timer->hoursStream, timer->minutesStream, timer->secondsStream); + ui->streamTime->setText(timer->textStream); +} + +void OutputTimer::UpdateRecordTimerDisplay() +{ + timer->recordTimerDisplay--; + + timer->secondsRecord = timer->recordTimerDisplay % 60; + timer->totalMinutesRecord = timer->recordTimerDisplay / 60; + timer->minutesRecord = timer->totalMinutesRecord % 60; + timer->hoursRecord = timer->totalMinutesRecord / 60; + + timer->textRecord.sprintf("%02d:%02d:%02d", + timer->hoursRecord, timer->minutesRecord, timer->secondsRecord); + ui->recordTime->setText(timer->textRecord); +} + +void OutputTimer::ShowHideDialog() +{ + if (!isVisible()) { + setVisible(true); + QTimer::singleShot(250, this, SLOT(show())); + } else { + setVisible(false); + QTimer::singleShot(250, this, SLOT(hide())); + } +} + +void OutputTimer::EventStopStreaming() +{ + obs_frontend_streaming_stop(); +} + +void OutputTimer::EventStopRecording() +{ + obs_frontend_recording_stop(); +} + +static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *) +{ + if (saving) { + obs_data_t *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_obj(save_data, "output-timer", obj); + + obs_data_release(obj); + } else { + obs_data_t *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")); + + obs_data_release(obj); + } +} + +extern "C" void FreeOutputTimer() +{ + delete timer; + timer = nullptr; +} + +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(); + } +} + +extern "C" void InitOutputTimer() +{ + QAction *action = (QAction*)obs_frontend_add_tools_menu_qaction( + obs_module_text("OutputTimer")); + + timer = new TimerData; + + obs_frontend_push_ui_translation(obs_module_get_string); + + 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); +} diff --git a/UI/frontend-plugins/frontend-tools/output-timer.hpp b/UI/frontend-plugins/frontend-tools/output-timer.hpp new file mode 100644 index 00000000..d95b87a5 --- /dev/null +++ b/UI/frontend-plugins/frontend-tools/output-timer.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "ui_output-timer.h" + +class QCloseEvent; + +class OutputTimer : public QDialog { + Q_OBJECT + +public: + std::unique_ptr ui; + OutputTimer(QWidget *parent); + + void closeEvent(QCloseEvent *event) override; + +public slots: + void StreamingTimerButton(); + void RecordingTimerButton(); + void StreamTimerStart(); + void RecordTimerStart(); + void StreamTimerStop(); + void RecordTimerStop(); + void UpdateStreamTimerDisplay(); + void UpdateRecordTimerDisplay(); + void ShowHideDialog(); + void EventStopStreaming(); + void EventStopRecording(); +}; -- GitLab