diff --git a/UI/basic-controls.cpp b/UI/basic-controls.cpp new file mode 100644 index 00000000000000..00145281cc1fe2 --- /dev/null +++ b/UI/basic-controls.cpp @@ -0,0 +1,329 @@ +#include "basic-controls.hpp" + +#include "window-basic-main.hpp" + +OBSBasicControls::OBSBasicControls(OBSBasic *main) + : QFrame(nullptr), + ui(new Ui::OBSBasicControls) +{ + /* Create UI elements */ + ui->setupUi(this); + + streamButtonMenu.reset(new QMenu()); + startStreamAction = + streamButtonMenu->addAction(QTStr("Basic.Main.StartStreaming")); + stopStreamAction = + streamButtonMenu->addAction(QTStr("Basic.Main.StopStreaming")); + QAction *forceStopStreamAction = streamButtonMenu->addAction( + QTStr("Basic.Main.ForceStopStreaming")); + + /* Transfer buttons signals as OBSBasicControls signals */ + connect( + ui->streamButton, &QPushButton::clicked, this, + [this]() { emit this->StreamButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->broadcastButton, &QPushButton::clicked, this, + [this]() { emit this->BroadcastButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->recordButton, &QPushButton::clicked, this, + [this]() { emit this->RecordButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->pauseRecordButton, &QPushButton::clicked, this, + [this]() { emit this->PauseRecordButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->replayBufferButton, &QPushButton::clicked, this, + [this]() { emit this->ReplayBufferButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->saveReplayButton, &QPushButton::clicked, this, + [this]() { emit this->SaveReplayBufferButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->virtualCamButton, &QPushButton::clicked, this, + [this]() { emit this->VirtualCamButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->virtualCamConfigButton, &QPushButton::clicked, this, + [this]() { emit this->VirtualCamConfigButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->modeSwitch, &QPushButton::clicked, this, + [this]() { emit this->StudioModeButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->settingsButton, &QPushButton::clicked, this, + [this]() { emit this->SettingsButtonClicked(); }, + Qt::DirectConnection); + connect( + ui->exitButton, &QPushButton::clicked, this, + [this]() { emit this->ExitButtonClicked(); }, + Qt::DirectConnection); + + /* Transfer menu actions signals as OBSBasicControls signals */ + connect( + startStreamAction.get(), &QAction::triggered, this, + [this]() { emit this->StartStreamMenuActionClicked(); }, + Qt::DirectConnection); + connect( + stopStreamAction.get(), &QAction::triggered, this, + [this]() { emit this->StopStreamMenuActionClicked(); }, + Qt::DirectConnection); + connect( + forceStopStreamAction, &QAction::triggered, this, + [this]() { emit this->ForceStopStreamMenuActionClicked(); }, + Qt::DirectConnection); + + /* Set up default visibilty */ + ui->broadcastButton->setVisible(false); + ui->pauseRecordButton->setVisible(false); + ui->replayBufferButton->setVisible(false); + ui->saveReplayButton->setVisible(false); + ui->virtualCamButton->setVisible(false); + ui->virtualCamConfigButton->setVisible(false); + + /* Set up state update connections */ + connect(main, &OBSBasic::StreamingPreparing, this, + &OBSBasicControls::StreamingPreparing); + connect(main, &OBSBasic::StreamingStarting, this, + &OBSBasicControls::StreamingStarting); + connect(main, &OBSBasic::StreamingStarted, this, + &OBSBasicControls::StreamingStarted); + connect(main, &OBSBasic::StreamingStopping, this, + &OBSBasicControls::StreamingStopping); + connect(main, &OBSBasic::StreamingStopped, this, + &OBSBasicControls::StreamingStopped); + + connect(main, &OBSBasic::BroadcastStreamReady, this, + &OBSBasicControls::BroadcastStreamReady); + connect(main, &OBSBasic::BroadcastStreamActive, this, + &OBSBasicControls::BroadcastStreamActive); + connect(main, &OBSBasic::BroadcastStreamStarted, this, + &OBSBasicControls::BroadcastStreamStarted); + + connect(main, &OBSBasic::RecordingStarted, this, + &OBSBasicControls::RecordingStarted); + connect(main, &OBSBasic::RecordingPaused, this, + &OBSBasicControls::RecordingPaused); + connect(main, &OBSBasic::RecordingUnpaused, this, + &OBSBasicControls::RecordingUnpaused); + connect(main, &OBSBasic::RecordingStopping, this, + &OBSBasicControls::RecordingStopping); + connect(main, &OBSBasic::RecordingStopped, this, + &OBSBasicControls::RecordingStopped); + + connect(main, &OBSBasic::ReplayBufStarted, this, + &OBSBasicControls::ReplayBufferStarted); + connect(main, &OBSBasic::ReplayBufferStopping, this, + &OBSBasicControls::ReplayBufferStopping); + connect(main, &OBSBasic::ReplayBufStopped, this, + &OBSBasicControls::ReplayBufferStopped); + + connect(main, &OBSBasic::VirtualCamStarted, this, + &OBSBasicControls::VirtualCamStarted); + connect(main, &OBSBasic::VirtualCamStopped, this, + &OBSBasicControls::VirtualCamStopped); + + connect(main, &OBSBasic::PreviewProgramModeChanged, this, + &OBSBasicControls::UpdateStudioModeState); + + /* Set up enablement connection */ + connect(main, &OBSBasic::BroadcastFlowEnabled, this, + &OBSBasicControls::EnableBroadcastFlow); + connect(main, &OBSBasic::ReplayBufEnabled, this, + &OBSBasicControls::EnableReplayBufferButtons); + connect(main, &OBSBasic::VirtualCamEnabled, this, + &OBSBasicControls::EnableVirtualCamButtons); +} + +void OBSBasicControls::StreamingPreparing() +{ + ui->streamButton->setEnabled(false); + ui->streamButton->setText(QTStr("Basic.Main.PreparingStream")); +} + +void OBSBasicControls::StreamingStarting(bool broadcastAutoStart) +{ + ui->streamButton->setText(QTStr("Basic.Main.Connecting")); + + if (!broadcastAutoStart) { + // well, we need to disable button while stream is not active + ui->broadcastButton->setEnabled(false); + + ui->broadcastButton->setText( + QTStr("Basic.Main.StartBroadcast")); + + ui->broadcastButton->setProperty("broadcastState", "ready"); + ui->broadcastButton->style()->unpolish(ui->broadcastButton); + ui->broadcastButton->style()->polish(ui->broadcastButton); + } +} + +void OBSBasicControls::StreamingStarted(bool withDelay) +{ + ui->streamButton->setEnabled(true); + ui->streamButton->setChecked(true); + ui->streamButton->setText(QTStr("Basic.Main.StopStreaming")); + + if (withDelay) { + ui->streamButton->setMenu(streamButtonMenu.get()); + startStreamAction->setVisible(false); + stopStreamAction->setVisible(true); + } +} + +void OBSBasicControls::StreamingStopping() +{ + ui->streamButton->setText(QTStr("Basic.Main.StoppingStreaming")); +} + +void OBSBasicControls::StreamingStopped(bool withDelay) +{ + ui->streamButton->setEnabled(true); + ui->streamButton->setChecked(false); + ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); + + if (withDelay) { + if (!ui->streamButton->menu()) + ui->streamButton->setMenu(streamButtonMenu.get()); + + startStreamAction->setVisible(true); + stopStreamAction->setVisible(false); + } else { + ui->streamButton->setMenu(nullptr); + } +} + +void OBSBasicControls::BroadcastStreamReady(bool ready) +{ + ui->broadcastButton->setChecked(ready); +} + +void OBSBasicControls::BroadcastStreamActive() +{ + ui->broadcastButton->setEnabled(true); +} + +void OBSBasicControls::BroadcastStreamStarted(bool autoStop) +{ + ui->broadcastButton->setText( + QTStr(autoStop ? "Basic.Main.AutoStopEnabled" + : "Basic.Main.StopBroadcast")); + if (autoStop) + ui->broadcastButton->setEnabled(false); + + ui->broadcastButton->setProperty("broadcastState", "active"); + ui->broadcastButton->style()->unpolish(ui->broadcastButton); + ui->broadcastButton->style()->polish(ui->broadcastButton); +} + +void OBSBasicControls::RecordingStarted(bool pausable) +{ + ui->recordButton->setChecked(true); + ui->recordButton->setText(QTStr("Basic.Main.StopRecording")); + + if (pausable) { + ui->pauseRecordButton->setVisible(pausable); + RecordingUnpaused(); + } +} + +void OBSBasicControls::RecordingPaused() +{ + QString text = QTStr("Basic.Main.UnpauseRecording"); + + ui->pauseRecordButton->setChecked(true); + ui->pauseRecordButton->setAccessibleName(text); + ui->pauseRecordButton->setToolTip(text); + + ui->saveReplayButton->setEnabled(false); +} + +void OBSBasicControls::RecordingUnpaused() +{ + QString text = QTStr("Basic.Main.PauseRecording"); + + ui->pauseRecordButton->setChecked(false); + ui->pauseRecordButton->setAccessibleName(text); + ui->pauseRecordButton->setToolTip(text); + + ui->saveReplayButton->setEnabled(true); +} + +void OBSBasicControls::RecordingStopping() +{ + ui->recordButton->setText(QTStr("Basic.Main.StoppingRecording")); +} + +void OBSBasicControls::RecordingStopped() +{ + ui->recordButton->setChecked(false); + ui->recordButton->setText(QTStr("Basic.Main.StartRecording")); + + ui->pauseRecordButton->setVisible(false); +} + +void OBSBasicControls::ReplayBufferStarted() +{ + ui->replayBufferButton->setChecked(true); + ui->replayBufferButton->setText(QTStr("Basic.Main.StopReplayBuffer")); + + ui->saveReplayButton->setVisible(true); +} + +void OBSBasicControls::ReplayBufferStopping() +{ + ui->replayBufferButton->setText( + QTStr("Basic.Main.StoppingReplayBuffer")); +} + +void OBSBasicControls::ReplayBufferStopped() +{ + ui->replayBufferButton->setChecked(false); + ui->replayBufferButton->setText(QTStr("Basic.Main.StartReplayBuffer")); + + ui->saveReplayButton->setVisible(false); +} + +void OBSBasicControls::VirtualCamStarted() +{ + ui->virtualCamButton->setChecked(true); + ui->virtualCamButton->setText(QTStr("Basic.Main.StopVirtualCam")); +} + +void OBSBasicControls::VirtualCamStopped() +{ + ui->virtualCamButton->setChecked(false); + ui->virtualCamButton->setText(QTStr("Basic.Main.StartVirtualCam")); +} + +void OBSBasicControls::UpdateStudioModeState(bool enabled) +{ + ui->modeSwitch->setChecked(enabled); +} + +void OBSBasicControls::EnableBroadcastFlow(bool enabled) +{ + ui->broadcastButton->setVisible(enabled); + ui->broadcastButton->setEnabled(enabled); + + ui->broadcastButton->setText(QTStr("Basic.Main.SetupBroadcast")); + + ui->broadcastButton->setProperty("broadcastState", "idle"); + ui->broadcastButton->style()->unpolish(ui->broadcastButton); + ui->broadcastButton->style()->polish(ui->broadcastButton); +} + +void OBSBasicControls::EnableReplayBufferButtons(bool enabled) +{ + ui->replayBufferButton->setVisible(enabled); +} + +void OBSBasicControls::EnableVirtualCamButtons() +{ + ui->virtualCamButton->setVisible(true); + ui->virtualCamConfigButton->setVisible(true); +} diff --git a/UI/basic-controls.hpp b/UI/basic-controls.hpp new file mode 100644 index 00000000000000..6aa6778028ce54 --- /dev/null +++ b/UI/basic-controls.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include + +#include +#include +#include + +class OBSBasic; + +#include "ui_OBSBasicControls.h" + +class OBSBasicControls : public QFrame { + Q_OBJECT + + std::unique_ptr ui; + + QScopedPointer streamButtonMenu; + QPointer startStreamAction; + QPointer stopStreamAction; + +private slots: + void StreamingPreparing(); + void StreamingStarting(bool broadcastAutoStart); + void StreamingStarted(bool withDelay); + void StreamingStopping(); + void StreamingStopped(bool withDelay); + + void BroadcastStreamReady(bool ready); + void BroadcastStreamActive(); + void BroadcastStreamStarted(bool autoStop); + + void RecordingStarted(bool pausable); + void RecordingPaused(); + void RecordingUnpaused(); + void RecordingStopping(); + void RecordingStopped(); + + void ReplayBufferStarted(); + void ReplayBufferStopping(); + void ReplayBufferStopped(); + + void VirtualCamStarted(); + void VirtualCamStopped(); + + void UpdateStudioModeState(bool enabled); + + void EnableBroadcastFlow(bool enabled); + void EnableReplayBufferButtons(bool enabled); + void EnableVirtualCamButtons(); + +public: + OBSBasicControls(OBSBasic *main); + inline ~OBSBasicControls() {} + +signals: + void StreamButtonClicked(); + void BroadcastButtonClicked(); + void RecordButtonClicked(); + void PauseRecordButtonClicked(); + void ReplayBufferButtonClicked(); + void SaveReplayBufferButtonClicked(); + void VirtualCamButtonClicked(); + void VirtualCamConfigButtonClicked(); + void StudioModeButtonClicked(); + void SettingsButtonClicked(); + void ExitButtonClicked(); + + void StartStreamMenuActionClicked(); + void StopStreamMenuActionClicked(); + void ForceStopStreamMenuActionClicked(); +}; diff --git a/UI/cmake/legacy.cmake b/UI/cmake/legacy.cmake index 5351f16f626d67..dc2800464ac60b 100644 --- a/UI/cmake/legacy.cmake +++ b/UI/cmake/legacy.cmake @@ -101,6 +101,7 @@ target_sources( forms/OBSAbout.ui forms/OBSAdvAudio.ui forms/OBSBasic.ui + forms/OBSBasicControls.ui forms/OBSBasicFilters.ui forms/OBSBasicInteraction.ui forms/OBSBasicProperties.ui @@ -167,6 +168,8 @@ target_sources( audio-encoders.cpp audio-encoders.hpp balance-slider.hpp + basic-controls.cpp + basic-controls.hpp clickable-label.hpp double-slider.cpp double-slider.hpp @@ -189,13 +192,12 @@ target_sources( menu-button.cpp menu-button.hpp mute-checkbox.hpp + noncheckable-button.hpp plain-text-edit.cpp plain-text-edit.hpp properties-view.cpp properties-view.hpp properties-view.moc.hpp - record-button.cpp - record-button.hpp remote-text.cpp remote-text.hpp scene-tree.cpp diff --git a/UI/cmake/ui-elements.cmake b/UI/cmake/ui-elements.cmake index 4b4ccb66e1f27f..d3f6f44ec29aac 100644 --- a/UI/cmake/ui-elements.cmake +++ b/UI/cmake/ui-elements.cmake @@ -38,6 +38,8 @@ target_sources( audio-encoders.cpp audio-encoders.hpp balance-slider.hpp + basic-controls.cpp + basic-controls.hpp context-bar-controls.cpp context-bar-controls.hpp focus-list.cpp @@ -55,8 +57,7 @@ target_sources( menu-button.cpp menu-button.hpp mute-checkbox.hpp - record-button.cpp - record-button.hpp + noncheckable-button.hpp remote-text.cpp remote-text.hpp scene-tree.cpp diff --git a/UI/cmake/ui-qt.cmake b/UI/cmake/ui-qt.cmake index 4989d2d1153a5d..6148fda8854924 100644 --- a/UI/cmake/ui-qt.cmake +++ b/UI/cmake/ui-qt.cmake @@ -34,6 +34,7 @@ set(_qt_sources forms/OBSAbout.ui forms/OBSAdvAudio.ui forms/OBSBasic.ui + forms/OBSBasicControls.ui forms/OBSBasicFilters.ui forms/OBSBasicInteraction.ui forms/OBSBasicProperties.ui diff --git a/UI/data/themes/Yami.obt b/UI/data/themes/Yami.obt index 91b48ddc4a2df9..51e85a62a88532 100644 --- a/UI/data/themes/Yami.obt +++ b/UI/data/themes/Yami.obt @@ -985,16 +985,24 @@ QDoubleSpinBox::down-arrow { #streamButton, #recordButton, -QPushButton[themeID="replayBufferButton"], +#replayBufferButton, #broadcastButton { padding: var(--padding_large); } +#pauseRecordButton, +#saveReplayButton, +#virtualCamConfigButton { + padding: var(--padding_large) var(--padding_large); + width: var(--input_height); + max-width: var(--input_height); +} + /* Primary Control Button Checked Coloring */ #streamButton:!hover:!pressed:checked, #recordButton:!hover:!pressed:checked, -QPushButton[themeID="replayBufferButton"]:!hover:!pressed:checked, -QPushButton[themeID="vcamButton"]:!hover:!pressed:checked, +#replayBufferButton:!hover:!pressed:checked, +#virtualCamButton:!hover:!pressed:checked, #modeSwitch:!hover:!pressed:checked, #broadcastButton:!hover:!pressed:checked { background: var(--primary); @@ -1003,8 +1011,8 @@ QPushButton[themeID="vcamButton"]:!hover:!pressed:checked, /* Primary Control Button Hover Coloring */ #streamButton:hover:!pressed:checked, #recordButton:hover:!pressed:checked, -QPushButton[themeID="replayBufferButton"]:!pressed:checked, -QPushButton[themeID="vcamButton"]:!pressed:checked, +#replayBufferButton:!pressed:checked, +#virtualCamButton:!pressed:checked, #modeSwitch:hover:!pressed:checked, #broadcastButton:hover:!pressed:checked { background: var(--primary_light); diff --git a/UI/data/themes/Yami_Acri.ovt b/UI/data/themes/Yami_Acri.ovt index d727a804fc7f55..8f87eaebece9ba 100644 --- a/UI/data/themes/Yami_Acri.ovt +++ b/UI/data/themes/Yami_Acri.ovt @@ -147,8 +147,8 @@ QTabBar QToolButton { /* Primary Control Button Checked Coloring */ #streamButton:!hover:!pressed:checked, #recordButton:!hover:!pressed:checked, -QPushButton[themeID="replayBufferButton"]:!hover:!pressed:checked, -QPushButton[themeID="vcamButton"]:!hover:!pressed:checked, +#replayBufferButton:!hover:!pressed:checked, +#virtualCamButton:!hover:!pressed:checked, #modeSwitch:!hover:!pressed:checked, #broadcastButton:!hover:!pressed:checked { background: var(--button_bg_red); @@ -158,8 +158,8 @@ QPushButton[themeID="vcamButton"]:!hover:!pressed:checked, /* Primary Control Button Hover Coloring */ #streamButton:hover:!pressed:checked, #recordButton:hover:!pressed:checked, -QPushButton[themeID="replayBufferButton"]:!pressed:checked, -QPushButton[themeID="vcamButton"]:!pressed:checked, +#replayBufferButton:hover:!pressed:checked, +#virtualCamButton:hover:!pressed:checked, #modeSwitch:hover:!pressed:checked, #broadcastButton:hover:!pressed:checked { background: var(--button_bg_red_hover); @@ -168,8 +168,8 @@ QPushButton[themeID="vcamButton"]:!pressed:checked, /* Primary Control Button Checked + Pressed Coloring */ #streamButton:pressed:checked, #recordButton:pressed:checked, -QPushButton[themeID="replayBufferButton"]:pressed:checked, -QPushButton[themeID="vcamButton"]:pressed:checked, +#replayBufferButton:pressed:checked, +#virtualCamButton:pressed:checked, #modeSwitch:pressed:checked, #broadcastButton:pressed:checked { background: var(--button_bg_red_down); diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index a0313b2b4e6549..052d867350099b 100644 --- a/UI/forms/OBSBasic.ui +++ b/UI/forms/OBSBasic.ui @@ -1399,228 +1399,6 @@ - - - QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable - - - Basic.Main.Controls - - - 8 - - - - - 0 - - - 1 - - - 0 - - - 1 - - - 1 - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - true - - - - 0 - 0 - - - - - 150 - 0 - - - - Basic.Main.StartStreaming - - - true - - - - - - - true - - - - 0 - 0 - - - - - 150 - 0 - - - - Basic.Main.StartBroadcast - - - true - - - - - - - - - 2 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - true - - - - 0 - 0 - - - - - 0 - 0 - - - - Basic.Main.StartRecording - - - true - - - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - Basic.TogglePreviewProgramMode - - - true - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - Settings - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - Exit - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - - @@ -2372,11 +2150,6 @@
window-dock.hpp
1 - - RecordButton - QPushButton -
record-button.hpp
-
@@ -2398,21 +2171,5 @@ - - exitButton - clicked() - OBSBasic - close() - - - 976 - 601 - - - 862 - -11 - - - diff --git a/UI/forms/OBSBasicControls.ui b/UI/forms/OBSBasicControls.ui new file mode 100644 index 00000000000000..09ae9e500f8834 --- /dev/null +++ b/UI/forms/OBSBasicControls.ui @@ -0,0 +1,403 @@ + + + OBSBasicControls + + + + 0 + 0 + 318 + 213 + + + + + 0 + + + 1 + + + 0 + + + 1 + + + 1 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + true + + + + 0 + 0 + + + + + 150 + 0 + + + + Basic.Main.StartStreaming + + + true + + + + + + + true + + + + 0 + 0 + + + + + 150 + 0 + + + + Basic.Main.StartBroadcast + + + true + + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Basic.Main.StartRecording + + + true + + + + + + + true + + + + 0 + 0 + + + + Basic.Main.PauseRecording + + + Basic.Main.PauseRecording + + + + :/res/images/media-pause.svg:/res/images/media-pause.svg + + + true + + + pauseIconSmall + + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Basic.Main.StartReplayBuffer + + + true + + + + + + + true + + + + 0 + 0 + + + + Basic.Main.SaveReplay + + + Basic.Main.SaveReplay + + + + :/res/images/save.svg:/res/images/save.svg + + + replayIconSmall + + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Basic.Main.StartVirtualCam + + + true + + + + + + + true + + + + 0 + 0 + + + + Basic.Main.VirtualCamConfig + + + Basic.Main.VirtualCamConfig + + + + :/settings/images/settings/general.svg:/settings/images/settings/general.svg + + + configIconSmall + + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Basic.TogglePreviewProgramMode + + + true + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Settings + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Exit + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + NonCheckableButton + QPushButton +
noncheckable-button.hpp
+
+
+ + + + +
diff --git a/UI/noncheckable-button.hpp b/UI/noncheckable-button.hpp new file mode 100644 index 00000000000000..71d942ef31d3e0 --- /dev/null +++ b/UI/noncheckable-button.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +/* Button with its checked property not changed when clicked. + * Meant to be used in situations where manually changing the property + * is always preferred. */ +class NonCheckableButton : public QPushButton { + Q_OBJECT + + inline void nextCheckState() override {} + +public: + inline NonCheckableButton(QWidget *parent = nullptr) + : QPushButton(parent) + { + } + inline NonCheckableButton(const QString &text, + QWidget *parent = nullptr) + : QPushButton(text, parent) + { + } +}; diff --git a/UI/record-button.cpp b/UI/record-button.cpp deleted file mode 100644 index a33bbfdec9cbf7..00000000000000 --- a/UI/record-button.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "record-button.hpp" -#include "window-basic-main.hpp" - -void RecordButton::resizeEvent(QResizeEvent *event) -{ - OBSBasic *main = OBSBasic::Get(); - if (!main->pause) - return; - - QSize pauseSize = main->pause->size(); - int height = main->ui->recordButton->size().height(); - - if (pauseSize.height() != height || pauseSize.width() != height) { - main->pause->setMinimumSize(height, height); - main->pause->setMaximumSize(height, height); - } - - event->accept(); -} - -static QWidget *firstWidget(QLayoutItem *item) -{ - auto widget = item->widget(); - if (widget) - return widget; - - auto layout = item->layout(); - if (!layout) - return nullptr; - - auto n = layout->count(); - for (auto i = 0; i < n; i++) { - widget = firstWidget(layout->itemAt(i)); - if (widget) - return widget; - } - return nullptr; -} - -static QWidget *lastWidget(QLayoutItem *item) -{ - auto widget = item->widget(); - if (widget) - return widget; - - auto layout = item->layout(); - if (!layout) - return nullptr; - - for (auto i = layout->count(); i > 0; i--) { - widget = lastWidget(layout->itemAt(i - 1)); - if (widget) - return widget; - } - return nullptr; -} - -static QWidget *getNextWidget(QBoxLayout *container, QLayoutItem *item) -{ - for (auto i = 1, n = container->count(); i < n; i++) { - if (container->itemAt(i - 1) == item) - return firstWidget(container->itemAt(i)); - } - return nullptr; -} - -ControlsSplitButton::ControlsSplitButton(const QString &text, - const QVariant &themeID, - void (OBSBasic::*clicked)()) - : QHBoxLayout() -{ - button.reset(new QPushButton(text)); - button->setCheckable(true); - button->setProperty("themeID", themeID); - - button->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); - button->installEventFilter(this); - - OBSBasic *main = OBSBasic::Get(); - connect(button.data(), &QPushButton::clicked, main, clicked); - - addWidget(button.data()); -} - -void ControlsSplitButton::addIcon(const QString &name, const QVariant &themeID, - void (OBSBasic::*clicked)()) -{ - icon.reset(new QPushButton()); - icon->setAccessibleName(name); - icon->setToolTip(name); - icon->setChecked(false); - icon->setProperty("themeID", themeID); - - QSizePolicy sp; - sp.setHeightForWidth(true); - icon->setSizePolicy(sp); - - OBSBasic *main = OBSBasic::Get(); - connect(icon.data(), &QAbstractButton::clicked, main, clicked); - - addWidget(icon.data()); - QWidget::setTabOrder(button.data(), icon.data()); - - auto next = getNextWidget(main->ui->buttonsVLayout, this); - if (next) - QWidget::setTabOrder(icon.data(), next); -} - -void ControlsSplitButton::removeIcon() -{ - icon.reset(); -} - -void ControlsSplitButton::insert(int index) -{ - OBSBasic *main = OBSBasic::Get(); - auto count = main->ui->buttonsVLayout->count(); - if (index < 0) - index = 0; - else if (index > count) - index = count; - - main->ui->buttonsVLayout->insertLayout(index, this); - - QWidget *prev = button.data(); - - if (index > 0) { - prev = lastWidget(main->ui->buttonsVLayout->itemAt(index - 1)); - if (prev) - QWidget::setTabOrder(prev, button.data()); - prev = button.data(); - } - - if (icon) { - QWidget::setTabOrder(button.data(), icon.data()); - prev = icon.data(); - } - - if (index < count) { - auto next = firstWidget( - main->ui->buttonsVLayout->itemAt(index + 1)); - if (next) - QWidget::setTabOrder(prev, next); - } -} - -bool ControlsSplitButton::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::Resize && icon) { - QSize iconSize = icon->size(); - int height = button->height(); - - if (iconSize.height() != height || iconSize.width() != height) { - icon->setMinimumSize(height, height); - icon->setMaximumSize(height, height); - } - } - return QObject::eventFilter(obj, event); -} diff --git a/UI/record-button.hpp b/UI/record-button.hpp deleted file mode 100644 index ea8d40c7de1aee..00000000000000 --- a/UI/record-button.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include - -class RecordButton : public QPushButton { - Q_OBJECT - -public: - inline RecordButton(QWidget *parent = nullptr) : QPushButton(parent) {} - - virtual void resizeEvent(QResizeEvent *event) override; -}; - -class OBSBasic; - -class ControlsSplitButton : public QHBoxLayout { - Q_OBJECT - -public: - ControlsSplitButton(const QString &text, const QVariant &themeID, - void (OBSBasic::*clicked)()); - - void addIcon(const QString &name, const QVariant &themeID, - void (OBSBasic::*clicked)()); - void removeIcon(); - void insert(int index); - - inline QPushButton *first() { return button.data(); } - inline QPushButton *second() { return icon.data(); } - -protected: - virtual bool eventFilter(QObject *obj, QEvent *event) override; - -private: - QScopedPointer button; - QScopedPointer icon; -}; diff --git a/UI/window-basic-main-transitions.cpp b/UI/window-basic-main-transitions.cpp index edf3baf9ffa08e..60d1943206fa43 100644 --- a/UI/window-basic-main-transitions.cpp +++ b/UI/window-basic-main-transitions.cpp @@ -976,7 +976,7 @@ int OBSBasic::GetTbarPosition() return tBar->value(); } -void OBSBasic::on_modeSwitch_clicked() +void OBSBasic::TogglePreviewProgramMode() { SetPreviewProgramMode(!IsPreviewProgramMode()); } @@ -1607,8 +1607,8 @@ void OBSBasic::SetPreviewProgramMode(bool enabled) if (IsPreviewProgramMode() == enabled) return; - ui->modeSwitch->setChecked(enabled); os_atomic_set_bool(&previewProgramMode, enabled); + emit PreviewProgramModeChanged(enabled); if (IsPreviewProgramMode()) { if (!previewEnabled) diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 9f72c621cfc4f9..74e07e540af94b 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -47,6 +47,7 @@ #include "platform.hpp" #include "visibility-item-widget.hpp" #include "item-widget-helpers.hpp" +#include "basic-controls.hpp" #include "window-basic-settings.hpp" #include "window-namedialog.hpp" #include "window-basic-auto-config.hpp" @@ -332,7 +333,90 @@ OBSBasic::OBSBasic(QWidget *parent) ui->setupUi(this); ui->previewDisabledWidget->setVisible(false); - ui->broadcastButton->setVisible(false); + + /* Set up streaming connections */ + connect( + this, &OBSBasic::StreamingStarting, this, + [this] { this->streamingStarting = true; }, + Qt::DirectConnection); + connect( + this, &OBSBasic::StreamingStarted, this, + [this] { this->streamingStarting = false; }, + Qt::DirectConnection); + connect( + this, &OBSBasic::StreamingStopped, this, + [this] { this->streamingStarting = false; }, + Qt::DirectConnection); + + /* Set up recording connections */ + connect( + this, &OBSBasic::RecordingStarted, this, + [this]() { + this->recordingStarted = true; + this->recordingPaused = false; + }, + Qt::DirectConnection); + connect( + this, &OBSBasic::RecordingPaused, this, + [this]() { this->recordingPaused = true; }, + Qt::DirectConnection); + connect( + this, &OBSBasic::RecordingUnpaused, this, + [this]() { this->recordingPaused = false; }, + Qt::DirectConnection); + connect( + this, &OBSBasic::RecordingStopped, this, + [this]() { + this->recordingStarted = false; + this->recordingPaused = false; + }, + Qt::DirectConnection); + + /* Add controls dock */ + OBSBasicControls *controls = new OBSBasicControls(this); + controlsDock = new OBSDock(this); + controlsDock->setObjectName(QString::fromUtf8("controlsDock")); + controlsDock->setWindowTitle(QTStr("Basic.Main.Controls")); + /* Parenting is done there so controls will be deleted alongside controlsDock */ + controlsDock->setWidget(controls); + addDockWidget(Qt::BottomDockWidgetArea, controlsDock); + + connect(controls, &OBSBasicControls::StreamButtonClicked, this, + &OBSBasic::StreamActionTriggered); + + connect(controls, &OBSBasicControls::StartStreamMenuActionClicked, this, + &OBSBasic::StartStreaming); + connect(controls, &OBSBasicControls::StopStreamMenuActionClicked, this, + &OBSBasic::StopStreaming); + connect(controls, &OBSBasicControls::ForceStopStreamMenuActionClicked, + this, &OBSBasic::ForceStopStreaming); + + connect(controls, &OBSBasicControls::BroadcastButtonClicked, this, + &OBSBasic::BroadcastButtonClicked); + + connect(controls, &OBSBasicControls::RecordButtonClicked, this, + &OBSBasic::RecordActionTriggered); + connect(controls, &OBSBasicControls::PauseRecordButtonClicked, this, + &OBSBasic::RecordPauseToggled); + + connect(controls, &OBSBasicControls::ReplayBufferButtonClicked, this, + &OBSBasic::ReplayBufferActionTriggered); + connect(controls, &OBSBasicControls::SaveReplayBufferButtonClicked, + this, &OBSBasic::ReplayBufferSave); + + connect(controls, &OBSBasicControls::VirtualCamButtonClicked, this, + &OBSBasic::VirtualCamActionTriggered); + connect(controls, &OBSBasicControls::VirtualCamConfigButtonClicked, + this, &OBSBasic::OpenVirtualCamConfig); + + connect(controls, &OBSBasicControls::StudioModeButtonClicked, this, + &OBSBasic::TogglePreviewProgramMode); + + connect(controls, &OBSBasicControls::SettingsButtonClicked, this, + &OBSBasic::on_action_Settings_triggered); + + connect(controls, &OBSBasicControls::ExitButtonClicked, this, + &QMainWindow::close); startingDockLayout = saveState(); @@ -474,7 +558,7 @@ OBSBasic::OBSBasic(QWidget *parent) SETUP_DOCK(ui->sourcesDock); SETUP_DOCK(ui->mixerDock); SETUP_DOCK(ui->transitionsDock); - SETUP_DOCK(ui->controlsDock); + SETUP_DOCK(controlsDock); SETUP_DOCK(statsDock); #undef SETUP_DOCK @@ -533,9 +617,6 @@ OBSBasic::OBSBasic(QWidget *parent) connect(ui->scenes, &SceneTree::scenesReordered, []() { OBSProjector::UpdateMultiviewProjectors(); }); - connect(ui->broadcastButton, &QPushButton::clicked, this, - &OBSBasic::BroadcastButtonClicked); - connect(App(), &OBSApp::StyleChanged, this, [this]() { if (api) api->on_event(OBS_FRONTEND_EVENT_THEME_CHANGED); @@ -1941,7 +2022,7 @@ void OBSBasic::InitPrimitives() obs_leave_graphics(); } -void OBSBasic::ReplayBufferClicked() +void OBSBasic::ReplayBufferActionTriggered() { if (outputHandler->ReplayBufferActive()) StopReplayBuffer(); @@ -1949,19 +2030,6 @@ void OBSBasic::ReplayBufferClicked() StartReplayBuffer(); }; -void OBSBasic::AddVCamButton() -{ - vcamButton = new ControlsSplitButton( - QTStr("Basic.Main.StartVirtualCam"), "vcamButton", - &OBSBasic::VCamButtonClicked); - vcamButton->addIcon(QTStr("Basic.Main.VirtualCamConfig"), - QStringLiteral("configIconSmall"), - &OBSBasic::VCamConfigButtonClicked); - vcamButton->insert(2); - vcamButton->first()->setSizePolicy(QSizePolicy::Minimum, - QSizePolicy::Minimum); -} - void OBSBasic::ResetOutputs() { ProfileScope("OBSBasic::ResetOutputs"); @@ -1975,19 +2043,13 @@ void OBSBasic::ResetOutputs() outputHandler.reset(advOut ? CreateAdvancedOutputHandler(this) : CreateSimpleOutputHandler(this)); - delete replayBufferButton; - - if (outputHandler->replayBuffer) { - replayBufferButton = new ControlsSplitButton( - QTStr("Basic.Main.StartReplayBuffer"), - "replayBufferButton", - &OBSBasic::ReplayBufferClicked); - replayBufferButton->insert(2); - } + emit ReplayBufEnabled(outputHandler->replayBuffer); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setEnabled( !!outputHandler->replayBuffer); + + UpdateIsRecordingPausable(); } else { outputHandler->Update(); } @@ -2123,7 +2185,7 @@ void OBSBasic::OBSInit() vcamEnabled = (obs_get_output_flags(VIRTUAL_CAM_ID) & OBS_OUTPUT_VIDEO) != 0; if (vcamEnabled) { - AddVCamButton(); + emit VirtualCamEnabled(); } InitBasicConfigDefaults2(); @@ -2771,10 +2833,10 @@ void OBSBasic::CreateHotkeys() "OBSBasic.StartStreaming", Str("Basic.Main.StartStreaming"), "OBSBasic.StopStreaming", Str("Basic.Main.StopStreaming"), MAKE_CALLBACK(!basic.outputHandler->StreamingActive() && - basic.ui->streamButton->isEnabled(), + !basic.streamingStarting, basic.StartStreaming, "Starting stream"), MAKE_CALLBACK(basic.outputHandler->StreamingActive() && - basic.ui->streamButton->isEnabled(), + !basic.streamingStarting, basic.StopStreaming, "Stopping stream"), this, this); LoadHotkeyPair(streamingHotkeys, "OBSBasic.StartStreaming", @@ -2796,10 +2858,10 @@ void OBSBasic::CreateHotkeys() "OBSBasic.StartRecording", Str("Basic.Main.StartRecording"), "OBSBasic.StopRecording", Str("Basic.Main.StopRecording"), MAKE_CALLBACK(!basic.outputHandler->RecordingActive() && - !basic.ui->recordButton->isChecked(), + !basic.recordingStarted, basic.StartRecording, "Starting recording"), MAKE_CALLBACK(basic.outputHandler->RecordingActive() && - basic.ui->recordButton->isChecked(), + basic.recordingStarted, basic.StopRecording, "Stopping recording"), this, this); LoadHotkeyPair(recordingHotkeys, "OBSBasic.StartRecording", @@ -2808,9 +2870,11 @@ void OBSBasic::CreateHotkeys() pauseHotkeys = obs_hotkey_pair_register_frontend( "OBSBasic.PauseRecording", Str("Basic.Main.PauseRecording"), "OBSBasic.UnpauseRecording", Str("Basic.Main.UnpauseRecording"), - MAKE_CALLBACK(basic.pause && !basic.pause->isChecked(), + MAKE_CALLBACK(basic.isRecordingPausable && + !basic.recordingPaused, basic.PauseRecording, "Pausing recording"), - MAKE_CALLBACK(basic.pause && basic.pause->isChecked(), + MAKE_CALLBACK(basic.isRecordingPausable && + basic.recordingPaused, basic.UnpauseRecording, "Unpausing recording"), this, this); LoadHotkeyPair(pauseHotkeys, "OBSBasic.PauseRecording", @@ -6895,12 +6959,11 @@ void OBSBasic::DisplayStreamStartError() QString message = !outputHandler->lastError.empty() ? QTStr(outputHandler->lastError.c_str()) : QTStr("Output.StartFailedGeneric"); - ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(false); + + emit StreamingStopped(); if (sysTrayStream) { - sysTrayStream->setText(ui->streamButton->text()); + sysTrayStream->setText(QTStr("Basic.Main.StartStreaming")); sysTrayStream->setEnabled(true); } @@ -6931,6 +6994,8 @@ void OBSBasic::YouTubeActionDialogOk(const QString &broadcast_id, autoStopBroadcast = autostop; broadcastReady = true; + emit BroadcastStreamReady(broadcastReady); + if (start_now) QMetaObject::invokeMethod(this, "StartStreaming"); } @@ -6973,9 +7038,7 @@ void OBSBasic::YoutubeStreamCheck(const std::string &key) auto item = json["items"][0]; auto status = item["status"]["streamStatus"].string_value(); if (status == "active") { - QMetaObject::invokeMethod(ui->broadcastButton, - "setEnabled", - Q_ARG(bool, true)); + emit BroadcastStreamActive(); break; } else { QThread::sleep(1); @@ -7027,8 +7090,6 @@ void OBSBasic::StartStreaming() if (auth && auth->broadcastFlow()) { if (!broadcastActive && !broadcastReady) { - ui->streamButton->setChecked(false); - QMessageBox no_broadcast(this); no_broadcast.setText(QTStr("Output.NoBroadcast.Text")); QPushButton *SetupBroadcast = no_broadcast.addButton( @@ -7049,87 +7110,57 @@ void OBSBasic::StartStreaming() } } - auto setStreamText = [&](const QString &text) { - ui->streamButton->setText(text); - if (sysTrayStream) - sysTrayStream->setText(text); - }; + emit StreamingPreparing(); - ui->streamButton->setEnabled(false); - ui->streamButton->setChecked(false); - ui->broadcastButton->setChecked(false); - if (sysTrayStream) + if (sysTrayStream) { sysTrayStream->setEnabled(false); - - setStreamText(QTStr("Basic.Main.PreparingStream")); + sysTrayStream->setText("Basic.Main.PreparingStream"); + } auto holder = outputHandler->SetupStreaming(service); - auto future = holder.future.then( - this, [&, setStreamText](bool setupStreamingResult) { - if (!setupStreamingResult) { - DisplayStreamStartError(); - return; - } + auto future = holder.future.then(this, [&](bool setupStreamingResult) { + if (!setupStreamingResult) { + DisplayStreamStartError(); + return; + } - if (api) - api->on_event( - OBS_FRONTEND_EVENT_STREAMING_STARTING); + if (api) + api->on_event(OBS_FRONTEND_EVENT_STREAMING_STARTING); - SaveProject(); + SaveProject(); - setStreamText(QTStr("Basic.Main.Connecting")); + emit StreamingStarting(autoStartBroadcast); - if (!outputHandler->StartStreaming(service)) { - DisplayStreamStartError(); - return; - } + if (sysTrayStream) + sysTrayStream->setText("Basic.Main.Connecting"); - if (!autoStartBroadcast) { - ui->broadcastButton->setText( - QTStr("Basic.Main.StartBroadcast")); - ui->broadcastButton->setProperty( - "broadcastState", "ready"); - ui->broadcastButton->style()->unpolish( - ui->broadcastButton); - ui->broadcastButton->style()->polish( - ui->broadcastButton); - // well, we need to disable button while stream is not active - ui->broadcastButton->setEnabled(false); - } else { - if (!autoStopBroadcast) { - ui->broadcastButton->setText(QTStr( - "Basic.Main.StopBroadcast")); - } else { - ui->broadcastButton->setText(QTStr( - "Basic.Main.AutoStopEnabled")); - ui->broadcastButton->setEnabled(false); - } - ui->broadcastButton->setProperty( - "broadcastState", "active"); - ui->broadcastButton->style()->unpolish( - ui->broadcastButton); - ui->broadcastButton->style()->polish( - ui->broadcastButton); - broadcastActive = true; - } + if (!outputHandler->StartStreaming(service)) { + DisplayStreamStartError(); + return; + } + + if (autoStartBroadcast) { + emit BroadcastStreamStarted(autoStopBroadcast); + broadcastActive = true; + } - bool recordWhenStreaming = config_get_bool( - GetGlobalConfig(), "BasicWindow", - "RecordWhenStreaming"); - if (recordWhenStreaming) - StartRecording(); + bool recordWhenStreaming = + config_get_bool(GetGlobalConfig(), "BasicWindow", + "RecordWhenStreaming"); + if (recordWhenStreaming) + StartRecording(); - bool replayBufferWhileStreaming = config_get_bool( - GetGlobalConfig(), "BasicWindow", - "ReplayBufferWhileStreaming"); - if (replayBufferWhileStreaming) - StartReplayBuffer(); + bool replayBufferWhileStreaming = + config_get_bool(GetGlobalConfig(), "BasicWindow", + "ReplayBufferWhileStreaming"); + if (replayBufferWhileStreaming) + StartReplayBuffer(); #ifdef YOUTUBE_ENABLED - if (!autoStartBroadcast) - OBSBasic::ShowYouTubeAutoStartWarning(); + if (!autoStartBroadcast) + OBSBasic::ShowYouTubeAutoStartWarning(); #endif - }); + }); startStreamingFuture = {holder.cancelAll, future}; } @@ -7138,8 +7169,6 @@ void OBSBasic::BroadcastButtonClicked() if (!broadcastReady || (!broadcastActive && !outputHandler->StreamingActive())) { SetupBroadcast(); - if (broadcastReady) - ui->broadcastButton->setChecked(true); return; } @@ -7163,7 +7192,6 @@ void OBSBasic::BroadcastButtonClicked() this, QTStr("Output.BroadcastStartFailed"), last_error, true); - ui->broadcastButton->setChecked(false); return; } } @@ -7171,18 +7199,7 @@ void OBSBasic::BroadcastButtonClicked() broadcastActive = true; autoStartBroadcast = true; // and clear the flag - if (!autoStopBroadcast) { - ui->broadcastButton->setText( - QTStr("Basic.Main.StopBroadcast")); - } else { - ui->broadcastButton->setText( - QTStr("Basic.Main.AutoStopEnabled")); - ui->broadcastButton->setEnabled(false); - } - - ui->broadcastButton->setProperty("broadcastState", "active"); - ui->broadcastButton->style()->unpolish(ui->broadcastButton); - ui->broadcastButton->style()->polish(ui->broadcastButton); + emit BroadcastStreamStarted(autoStopBroadcast); } else if (!autoStopBroadcast) { #ifdef YOUTUBE_ENABLED bool confirm = config_get_bool(GetGlobalConfig(), "BasicWindow", @@ -7194,10 +7211,8 @@ void OBSBasic::BroadcastButtonClicked() QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (button == QMessageBox::No) { - ui->broadcastButton->setChecked(true); + if (button == QMessageBox::No) return; - } } std::shared_ptr ytAuth = @@ -7226,19 +7241,14 @@ void OBSBasic::BroadcastButtonClicked() autoStopBroadcast = true; QMetaObject::invokeMethod(this, "StopStreaming"); + emit BroadcastStreamReady(broadcastReady); SetBroadcastFlowEnabled(true); } } void OBSBasic::SetBroadcastFlowEnabled(bool enabled) { - ui->broadcastButton->setEnabled(enabled); - ui->broadcastButton->setVisible(enabled); - ui->broadcastButton->setChecked(broadcastReady); - ui->broadcastButton->setProperty("broadcastState", "idle"); - ui->broadcastButton->style()->unpolish(ui->broadcastButton); - ui->broadcastButton->style()->polish(ui->broadcastButton); - ui->broadcastButton->setText(QTStr("Basic.Main.SetupBroadcast")); + emit BroadcastFlowEnabled(enabled); } void OBSBasic::SetupBroadcast() @@ -7249,11 +7259,7 @@ void OBSBasic::SetupBroadcast() OBSYoutubeActions dialog(this, auth, broadcastReady); connect(&dialog, &OBSYoutubeActions::ok, this, &OBSBasic::YouTubeActionDialogOk); - int result = dialog.Valid() ? dialog.exec() : QDialog::Rejected; - if (result != QDialog::Accepted) { - if (!broadcastReady) - ui->broadcastButton->setChecked(false); - } + dialog.exec(); } #endif } @@ -7386,6 +7392,8 @@ void OBSBasic::StopStreaming() broadcastReady = false; } + emit BroadcastStreamReady(broadcastReady); + OnDeactivate(); bool recordWhenStreaming = config_get_bool( @@ -7426,6 +7434,8 @@ void OBSBasic::ForceStopStreaming() broadcastReady = false; } + emit BroadcastStreamReady(broadcastReady); + OnDeactivate(); bool recordWhenStreaming = config_get_bool( @@ -7447,25 +7457,13 @@ void OBSBasic::ForceStopStreaming() void OBSBasic::StreamDelayStarting(int sec) { - ui->streamButton->setText(QTStr("Basic.Main.StopStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(true); + emit StreamingStarted(true); if (sysTrayStream) { - sysTrayStream->setText(ui->streamButton->text()); + sysTrayStream->setText(QTStr("Basic.Main.StopStreaming")); sysTrayStream->setEnabled(true); } - if (!startStreamMenu.isNull()) - startStreamMenu->deleteLater(); - - startStreamMenu = new QMenu(); - startStreamMenu->addAction(QTStr("Basic.Main.StopStreaming"), this, - &OBSBasic::StopStreaming); - startStreamMenu->addAction(QTStr("Basic.Main.ForceStopStreaming"), this, - &OBSBasic::ForceStopStreaming); - ui->streamButton->setMenu(startStreamMenu); - ui->statusbar->StreamDelayStarting(sec); OnActivate(); @@ -7473,25 +7471,13 @@ void OBSBasic::StreamDelayStarting(int sec) void OBSBasic::StreamDelayStopping(int sec) { - ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(false); + emit StreamingStopped(true); if (sysTrayStream) { - sysTrayStream->setText(ui->streamButton->text()); + sysTrayStream->setText(QTStr("Basic.Main.StartStreaming")); sysTrayStream->setEnabled(true); } - if (!startStreamMenu.isNull()) - startStreamMenu->deleteLater(); - - startStreamMenu = new QMenu(); - startStreamMenu->addAction(QTStr("Basic.Main.StartStreaming"), this, - &OBSBasic::StartStreaming); - startStreamMenu->addAction(QTStr("Basic.Main.ForceStopStreaming"), this, - &OBSBasic::ForceStopStreaming); - ui->streamButton->setMenu(startStreamMenu); - ui->statusbar->StreamDelayStopping(sec); if (api) @@ -7500,15 +7486,12 @@ void OBSBasic::StreamDelayStopping(int sec) void OBSBasic::StreamingStart() { + emit StreamingStarted(); OBSOutputAutoRelease output = obs_frontend_get_streaming_output(); - - ui->streamButton->setText(QTStr("Basic.Main.StopStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(true); ui->statusbar->StreamStarted(output); if (sysTrayStream) { - sysTrayStream->setText(ui->streamButton->text()); + sysTrayStream->setText(QTStr("Basic.Main.StopStreaming")); sysTrayStream->setEnabled(true); } @@ -7544,10 +7527,10 @@ void OBSBasic::StreamingStart() void OBSBasic::StreamStopping() { - ui->streamButton->setText(QTStr("Basic.Main.StoppingStreaming")); + emit StreamingStopping(); if (sysTrayStream) - sysTrayStream->setText(ui->streamButton->text()); + sysTrayStream->setText(QTStr("Basic.Main.StoppingStreaming")); streamingStopping = true; if (api) @@ -7604,12 +7587,10 @@ void OBSBasic::StreamingStop(int code, QString last_error) ui->statusbar->StreamStopped(); - ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(false); + emit StreamingStopped(); if (sysTrayStream) { - sysTrayStream->setText(ui->streamButton->text()); + sysTrayStream->setText(QTStr("Basic.Main.StartStreaming")); sysTrayStream->setEnabled(true); } @@ -7645,12 +7626,6 @@ void OBSBasic::StreamingStop(int code, QString last_error) QSystemTrayIcon::Warning); } - if (!startStreamMenu.isNull()) { - ui->streamButton->setMenu(nullptr); - startStreamMenu->deleteLater(); - startStreamMenu = nullptr; - } - // Reset broadcast button state/text if (!broadcastActive) SetBroadcastFlowEnabled(auth && auth->broadcastFlow()); @@ -7745,13 +7720,11 @@ void OBSBasic::StartRecording() if (!OutputPathValid()) { OutputPathInvalidMessage(); - ui->recordButton->setChecked(false); return; } if (!IsFFmpegOutputToURL() && LowDiskSpace()) { DiskSpaceMessage(); - ui->recordButton->setChecked(false); return; } @@ -7760,16 +7733,15 @@ void OBSBasic::StartRecording() SaveProject(); - if (!outputHandler->StartRecording()) - ui->recordButton->setChecked(false); + outputHandler->StartRecording(); } void OBSBasic::RecordStopping() { - ui->recordButton->setText(QTStr("Basic.Main.StoppingRecording")); + emit RecordingStopping(); if (sysTrayRecord) - sysTrayRecord->setText(ui->recordButton->text()); + sysTrayRecord->setText(QTStr("Basic.Main.StoppingRecording")); recordingStopping = true; if (api) @@ -7789,11 +7761,10 @@ void OBSBasic::StopRecording() void OBSBasic::RecordingStart() { ui->statusbar->RecordingStarted(outputHandler->fileOutput); - ui->recordButton->setText(QTStr("Basic.Main.StopRecording")); - ui->recordButton->setChecked(true); + emit RecordingStarted(isRecordingPausable); if (sysTrayRecord) - sysTrayRecord->setText(ui->recordButton->text()); + sysTrayRecord->setText(QTStr("Basic.Main.StopRecording")); recordingStopping = false; if (api) @@ -7803,7 +7774,6 @@ void OBSBasic::RecordingStart() diskFullTimer->start(1000); OnActivate(); - UpdatePause(); blog(LOG_INFO, RECORDING_START); } @@ -7811,11 +7781,10 @@ void OBSBasic::RecordingStart() void OBSBasic::RecordingStop(int code, QString last_error) { ui->statusbar->RecordingStopped(); - ui->recordButton->setText(QTStr("Basic.Main.StartRecording")); - ui->recordButton->setChecked(false); + emit RecordingStopped(); if (sysTrayRecord) - sysTrayRecord->setText(ui->recordButton->text()); + sysTrayRecord->setText(QTStr("Basic.Main.StartRecording")); blog(LOG_INFO, RECORDING_STOP); @@ -7882,7 +7851,6 @@ void OBSBasic::RecordingStop(int code, QString last_error) AutoRemux(outputHandler->lastRecordingPath.c_str()); OnDeactivate(); - UpdatePause(false); } void OBSBasic::RecordingFileChanged(QString lastRecordingPath) @@ -7933,20 +7901,16 @@ void OBSBasic::StartReplayBuffer() if (disableOutputsRef) return; - if (!UIValidation::NoSourcesConfirmation(this)) { - replayBufferButton->first()->setChecked(false); + if (!UIValidation::NoSourcesConfirmation(this)) return; - } if (!OutputPathValid()) { OutputPathInvalidMessage(); - replayBufferButton->first()->setChecked(false); return; } if (LowDiskSpace()) { DiskSpaceMessage(); - replayBufferButton->first()->setChecked(false); return; } @@ -7955,9 +7919,8 @@ void OBSBasic::StartReplayBuffer() SaveProject(); - if (!outputHandler->StartReplayBuffer()) { - replayBufferButton->first()->setChecked(false); - } else if (os_atomic_load_bool(&recording_paused)) { + if (outputHandler->StartReplayBuffer() && + os_atomic_load_bool(&recording_paused)) { ShowReplayBufferPauseWarning(); } } @@ -7967,12 +7930,11 @@ void OBSBasic::ReplayBufferStopping() if (!outputHandler || !outputHandler->replayBuffer) return; - replayBufferButton->first()->setText( - QTStr("Basic.Main.StoppingReplayBuffer")); + emit ReplayBufStopping(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText( - replayBufferButton->first()->text()); + QTStr("Basic.Main.StoppingReplayBuffer")); replayBufferStopping = true; if (api) @@ -7997,20 +7959,17 @@ void OBSBasic::ReplayBufferStart() if (!outputHandler || !outputHandler->replayBuffer) return; - replayBufferButton->first()->setText( - QTStr("Basic.Main.StopReplayBuffer")); - replayBufferButton->first()->setChecked(true); + emit ReplayBufStarted(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText( - replayBufferButton->first()->text()); + QTStr("Basic.Main.StopReplayBuffer")); replayBufferStopping = false; if (api) api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED); OnActivate(); - UpdateReplayBuffer(); blog(LOG_INFO, REPLAY_BUFFER_START); } @@ -8058,13 +8017,11 @@ void OBSBasic::ReplayBufferStop(int code) if (!outputHandler || !outputHandler->replayBuffer) return; - replayBufferButton->first()->setText( - QTStr("Basic.Main.StartReplayBuffer")); - replayBufferButton->first()->setChecked(false); + emit ReplayBufStopped(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText( - replayBufferButton->first()->text()); + QTStr("Basic.Main.StartReplayBuffer")); blog(LOG_INFO, REPLAY_BUFFER_STOP); @@ -8098,7 +8055,6 @@ void OBSBasic::ReplayBufferStop(int code) api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED); OnDeactivate(); - UpdateReplayBuffer(false); } void OBSBasic::StartVirtualCam() @@ -8112,9 +8068,7 @@ void OBSBasic::StartVirtualCam() SaveProject(); - if (!outputHandler->StartVirtualCam()) { - vcamButton->first()->setChecked(false); - } + outputHandler->StartVirtualCam(); } void OBSBasic::StopVirtualCam() @@ -8135,10 +8089,10 @@ void OBSBasic::OnVirtualCamStart() if (!outputHandler || !outputHandler->virtualCam) return; - vcamButton->first()->setText(QTStr("Basic.Main.StopVirtualCam")); + emit VirtualCamStarted(); + if (sysTrayVirtualCam) sysTrayVirtualCam->setText(QTStr("Basic.Main.StopVirtualCam")); - vcamButton->first()->setChecked(true); if (api) api->on_event(OBS_FRONTEND_EVENT_VIRTUALCAM_STARTED); @@ -8153,10 +8107,10 @@ void OBSBasic::OnVirtualCamStop(int) if (!outputHandler || !outputHandler->virtualCam) return; - vcamButton->first()->setText(QTStr("Basic.Main.StartVirtualCam")); + emit VirtualCamStopped(); + if (sysTrayVirtualCam) sysTrayVirtualCam->setText(QTStr("Basic.Main.StartVirtualCam")); - vcamButton->first()->setChecked(false); if (api) api->on_event(OBS_FRONTEND_EVENT_VIRTUALCAM_STOPPED); @@ -8173,7 +8127,7 @@ void OBSBasic::OnVirtualCamStop(int) QTimer::singleShot(100, this, &OBSBasic::RestartingVirtualCam); } -void OBSBasic::on_streamButton_clicked() +void OBSBasic::StreamActionTriggered() { if (outputHandler->StreamingActive()) { bool confirm = config_get_bool(GetGlobalConfig(), "BasicWindow", @@ -8188,10 +8142,8 @@ void OBSBasic::on_streamButton_clicked() QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (button == QMessageBox::No) { - ui->streamButton->setChecked(true); + if (button == QMessageBox::No) return; - } confirm = false; } @@ -8204,18 +8156,14 @@ void OBSBasic::on_streamButton_clicked() QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (button == QMessageBox::No) { - ui->streamButton->setChecked(true); + if (button == QMessageBox::No) return; - } } StopStreaming(); } else { - if (!UIValidation::NoSourcesConfirmation(this)) { - ui->streamButton->setChecked(false); + if (!UIValidation::NoSourcesConfirmation(this)) return; - } Auth *auth = GetAuth(); @@ -8229,10 +8177,8 @@ void OBSBasic::on_streamButton_clicked() break; case StreamSettingsAction::OpenSettings: on_action_Settings_triggered(); - ui->streamButton->setChecked(false); return; case StreamSettingsAction::Cancel: - ui->streamButton->setChecked(false); return; } @@ -8257,10 +8203,8 @@ void OBSBasic::on_streamButton_clicked() this, QTStr("ConfirmBWTest.Title"), QTStr("ConfirmBWTest.Text")); - if (button == QMessageBox::No) { - ui->streamButton->setChecked(false); + if (button == QMessageBox::No) return; - } } else if (confirm && isVisible()) { QMessageBox::StandardButton button = OBSMessageBox::question( @@ -8269,17 +8213,15 @@ void OBSBasic::on_streamButton_clicked() QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (button == QMessageBox::No) { - ui->streamButton->setChecked(false); + if (button == QMessageBox::No) return; - } } StartStreaming(); } } -void OBSBasic::on_recordButton_clicked() +void OBSBasic::RecordActionTriggered() { if (outputHandler->RecordingActive()) { bool confirm = config_get_bool(GetGlobalConfig(), "BasicWindow", @@ -8293,37 +8235,31 @@ void OBSBasic::on_recordButton_clicked() QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (button == QMessageBox::No) { - ui->recordButton->setChecked(true); + if (button == QMessageBox::No) return; - } } StopRecording(); } else { - if (!UIValidation::NoSourcesConfirmation(this)) { - ui->recordButton->setChecked(false); + if (!UIValidation::NoSourcesConfirmation(this)) return; - } StartRecording(); } } -void OBSBasic::VCamButtonClicked() +void OBSBasic::VirtualCamActionTriggered() { if (outputHandler->VirtualCamActive()) { StopVirtualCam(); } else { - if (!UIValidation::NoSourcesConfirmation(this)) { - vcamButton->first()->setChecked(false); + if (!UIValidation::NoSourcesConfirmation(this)) return; - } StartVirtualCam(); } } -void OBSBasic::VCamConfigButtonClicked() +void OBSBasic::OpenVirtualCamConfig() { OBSBasicVCamConfig dialog(vcamConfig, outputHandler->VirtualCamActive(), this); @@ -8387,11 +8323,6 @@ void OBSBasic::RestartingVirtualCam() restartingVCam = false; } -void OBSBasic::on_settingsButton_clicked() -{ - on_action_Settings_triggered(); -} - void OBSBasic::on_actionHelpPortal_triggered() { QUrl url = QUrl("https://obsproject.com/help", QUrl::TolerantMode); @@ -9682,7 +9613,7 @@ void OBSBasic::on_resetDocks_triggered(bool force) QList docks{ui->scenesDock, ui->sourcesDock, ui->mixerDock, ui->transitionsDock, - ui->controlsDock}; + controlsDock}; QList sizes{cx22_5, cx22_5, mixerSize, cx5, cx21}; @@ -9690,7 +9621,7 @@ void OBSBasic::on_resetDocks_triggered(bool force) ui->sourcesDock->setVisible(true); ui->mixerDock->setVisible(true); ui->transitionsDock->setVisible(true); - ui->controlsDock->setVisible(true); + controlsDock->setVisible(true); statsDock->setVisible(false); statsDock->setFloating(true); @@ -9715,7 +9646,7 @@ void OBSBasic::on_lockDocks_toggled(bool lock) ui->sourcesDock->setFeatures(mainFeatures); ui->mixerDock->setFeatures(mainFeatures); ui->transitionsDock->setFeatures(mainFeatures); - ui->controlsDock->setFeatures(mainFeatures); + controlsDock->setFeatures(mainFeatures); statsDock->setFeatures(features); for (int i = extraDocks.size() - 1; i >= 0; i--) @@ -10018,13 +9949,13 @@ void OBSBasic::SystemTrayInit() &OBSBasic::IconActivated); connect(showHide, &QAction::triggered, this, &OBSBasic::ToggleShowHide); connect(sysTrayStream, &QAction::triggered, this, - &OBSBasic::on_streamButton_clicked); + &OBSBasic::StreamActionTriggered); connect(sysTrayRecord, &QAction::triggered, this, - &OBSBasic::on_recordButton_clicked); + &OBSBasic::RecordActionTriggered); connect(sysTrayReplayBuffer.data(), &QAction::triggered, this, - &OBSBasic::ReplayBufferClicked); + &OBSBasic::ReplayBufferActionTriggered); connect(sysTrayVirtualCam.data(), &QAction::triggered, this, - &OBSBasic::VCamButtonClicked); + &OBSBasic::VirtualCamActionTriggered); connect(exit, &QAction::triggered, this, &OBSBasic::close); } @@ -10787,7 +10718,8 @@ void OBSBasic::UpdatePatronJson(const QString &text, const QString &error) void OBSBasic::PauseRecording() { - if (!pause || !outputHandler || !outputHandler->fileOutput || + if (!isRecordingPausable || !outputHandler || + !outputHandler->fileOutput || os_atomic_load_bool(&recording_paused)) return; @@ -10796,11 +10728,7 @@ void OBSBasic::PauseRecording() if (obs_output_pause(output, true)) { os_atomic_set_bool(&recording_paused, true); - pause->setAccessibleName(QTStr("Basic.Main.UnpauseRecording")); - pause->setToolTip(QTStr("Basic.Main.UnpauseRecording")); - pause->blockSignals(true); - pause->setChecked(true); - pause->blockSignals(false); + emit RecordingPaused(); ui->statusbar->RecordingPaused(); @@ -10818,11 +10746,6 @@ void OBSBasic::PauseRecording() trayIconFile)); } - auto replay = replayBufferButton ? replayBufferButton->second() - : nullptr; - if (replay) - replay->setEnabled(false); - if (api) api->on_event(OBS_FRONTEND_EVENT_RECORDING_PAUSED); @@ -10833,7 +10756,8 @@ void OBSBasic::PauseRecording() void OBSBasic::UnpauseRecording() { - if (!pause || !outputHandler || !outputHandler->fileOutput || + if (!isRecordingPausable || !outputHandler || + !outputHandler->fileOutput || !os_atomic_load_bool(&recording_paused)) return; @@ -10842,11 +10766,7 @@ void OBSBasic::UnpauseRecording() if (obs_output_pause(output, false)) { os_atomic_set_bool(&recording_paused, false); - pause->setAccessibleName(QTStr("Basic.Main.PauseRecording")); - pause->setToolTip(QTStr("Basic.Main.PauseRecording")); - pause->blockSignals(true); - pause->setChecked(false); - pause->blockSignals(false); + emit RecordingUnpaused(); ui->statusbar->RecordingUnpaused(); @@ -10864,19 +10784,15 @@ void OBSBasic::UnpauseRecording() trayIconFile)); } - auto replay = replayBufferButton ? replayBufferButton->second() - : nullptr; - if (replay) - replay->setEnabled(true); - if (api) api->on_event(OBS_FRONTEND_EVENT_RECORDING_UNPAUSED); } } -void OBSBasic::PauseToggled() +void OBSBasic::RecordPauseToggled() { - if (!pause || !outputHandler || !outputHandler->fileOutput) + if (!isRecordingPausable || !outputHandler || + !outputHandler->fileOutput) return; obs_output_t *output = outputHandler->fileOutput; @@ -10888,16 +10804,11 @@ void OBSBasic::PauseToggled() UnpauseRecording(); } -void OBSBasic::UpdatePause(bool activate) +void OBSBasic::UpdateIsRecordingPausable() { - if (!activate || !outputHandler || !outputHandler->RecordingActive()) { - pause.reset(); - return; - } - const char *mode = config_get_string(basicConfig, "Output", "Mode"); bool adv = astrcmpi(mode, "Advanced") == 0; - bool shared; + bool shared = true; if (adv) { const char *recType = @@ -10917,38 +10828,7 @@ void OBSBasic::UpdatePause(bool activate) shared = strcmp(quality, "Stream") == 0; } - if (!shared) { - pause.reset(new QPushButton()); - pause->setAccessibleName(QTStr("Basic.Main.PauseRecording")); - pause->setToolTip(QTStr("Basic.Main.PauseRecording")); - pause->setCheckable(true); - pause->setChecked(false); - pause->setProperty("themeID", - QVariant(QStringLiteral("pauseIconSmall"))); - - QSizePolicy sp; - sp.setHeightForWidth(true); - pause->setSizePolicy(sp); - - connect(pause.data(), &QAbstractButton::clicked, this, - &OBSBasic::PauseToggled); - ui->recordingLayout->addWidget(pause.data()); - } else { - pause.reset(); - } -} - -void OBSBasic::UpdateReplayBuffer(bool activate) -{ - if (!activate || !outputHandler || - !outputHandler->ReplayBufferActive()) { - replayBufferButton->removeIcon(); - return; - } - - replayBufferButton->addIcon(QTStr("Basic.Main.SaveReplay"), - QStringLiteral("replayIconSmall"), - &OBSBasic::ReplayBufferSave); + isRecordingPausable = !shared; } #define MBYTE (1024ULL * 1024ULL) diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 64d237446f5b5c..f68075ba3013ee 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -319,13 +319,8 @@ class OBSBasic : public OBSMainWindow { QPointer extraBrowsers; QPointer importer; - QPointer startStreamMenu; - QPointer transitionButton; - QPointer replayBufferButton; - QScopedPointer pause; - QPointer vcamButton; bool vcamEnabled = false; VCamConfig vcamConfig; @@ -546,8 +541,6 @@ class OBSBasic : public OBSMainWindow { void dragMoveEvent(QDragMoveEvent *event) override; void dropEvent(QDropEvent *event) override; - void ReplayBufferClicked(); - bool sysTrayMinimizeToTray(); void EnumDialogs(); @@ -677,6 +670,12 @@ class OBSBasic : public OBSMainWindow { void UpdatePreviewOverflowSettings(); + bool streamingStarting = false; + + bool recordingStarted = false; + bool isRecordingPausable = false; + bool recordingPaused = false; + bool restartingVCam = false; public slots: @@ -881,8 +880,7 @@ private slots: void AutoRemux(QString input, bool no_show = false); - void UpdatePause(bool activate = true); - void UpdateReplayBuffer(bool activate = true); + void UpdateIsRecordingPausable(); bool IsFFmpegOutputToURL() const; bool OutputPathValid(); @@ -926,7 +924,6 @@ private slots: int ResetVideo(); bool ResetAudio(); - void AddVCamButton(); void ResetOutputs(); void RefreshVolumeColors(); @@ -1125,11 +1122,6 @@ private slots: void on_actionScaleCanvas_triggered(); void on_actionScaleOutput_triggered(); - void on_streamButton_clicked(); - void on_recordButton_clicked(); - void VCamButtonClicked(); - void VCamConfigButtonClicked(); - void on_settingsButton_clicked(); void Screenshot(OBSSource source_ = nullptr); void ScreenshotSelectedSource(); void ScreenshotProgram(); @@ -1177,8 +1169,6 @@ private slots: void ShowTransitionProperties(); void HideTransitionProperties(); - void on_modeSwitch_clicked(); - // Source Context Buttons void on_sourcePropertiesButton_clicked(); void on_sourceFiltersButton_clicked(); @@ -1193,8 +1183,6 @@ private slots: void on_multiviewProjectorWindowed_triggered(); void on_sideDocks_toggled(bool side); - void PauseToggled(); - void logUploadFinished(const QString &text, const QString &error); void crashUploadFinished(const QString &text, const QString &error); void openLogDialog(const QString &text, const bool crash); @@ -1236,6 +1224,26 @@ private slots: void RepairOldExtraDockName(); void RepairCustomExtraDockName(); + /* Stream action (start/stop) slot */ + void StreamActionTriggered(); + + /* Record action (start/stop) slot */ + void RecordActionTriggered(); + + /* Record pause (pause/unpause) slot */ + void RecordPauseToggled(); + + /* Replay Buffer action (start/stop) slot */ + void ReplayBufferActionTriggered(); + + /* Virtual Cam action (start/stop) slots */ + void VirtualCamActionTriggered(); + + void OpenVirtualCamConfig(); + + /* Studio Mode toggle slot */ + void TogglePreviewProgramMode(); + public slots: void on_actionResetTransform_triggered(); @@ -1249,9 +1257,46 @@ public slots: void UpdateContextBarDeferred(bool force = false); void UpdateContextBarVisibility(); +signals: + /* Streaming signals */ + void StreamingPreparing(); + void StreamingStarting(bool broadcastAutoStart); + void StreamingStarted(bool withDelay = false); + void StreamingStopping(); + void StreamingStopped(bool withDelay = false); + + /* Broadcast Flow signals */ + void BroadcastFlowEnabled(bool enabled); + void BroadcastStreamReady(bool ready); + void BroadcastStreamActive(); + void BroadcastStreamStarted(bool autoStop); + + /* Recording signals */ + void RecordingStarted(bool pausable = false); + void RecordingPaused(); + void RecordingUnpaused(); + void RecordingStopping(); + void RecordingStopped(); + + /* Replay Buffer signals */ + void ReplayBufEnabled(bool enabled); + void ReplayBufStarted(); + void ReplayBufStopping(); + void ReplayBufStopped(); + + /* Virtual Camera signals */ + void VirtualCamEnabled(); + void VirtualCamStarted(); + void VirtualCamStopped(); + + /* Studio Mode signal */ + void PreviewProgramModeChanged(bool enabled); + private: std::unique_ptr ui; + QPointer controlsDock; + public: /* `undo_s` needs to be declared after `ui` to prevent an uninitialized * warning for `ui` while initializing `undo_s`. */