From 511385891c7616b4e4680c6da4d624b2b68923f6 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 3 Apr 2024 14:35:10 +0200 Subject: [PATCH] UI: Separate controls dock from the main window --- UI/basic-controls.cpp | 329 +++++++++++++++++++++++++++++ UI/basic-controls.hpp | 72 +++++++ UI/cmake/legacy.cmake | 6 +- UI/cmake/ui-elements.cmake | 5 +- UI/cmake/ui-qt.cmake | 1 + UI/data/themes/Yami.obt | 8 + UI/forms/OBSBasic.ui | 243 --------------------- UI/forms/OBSBasicControls.ui | 397 ++++++++++++++++++++++++++++++++++ UI/noncheckable-button.hpp | 23 ++ UI/record-button.cpp | 159 -------------- UI/record-button.hpp | 39 ---- UI/window-basic-main.cpp | 399 ++++++++++------------------------- UI/window-basic-main.hpp | 64 ++++-- 13 files changed, 988 insertions(+), 757 deletions(-) create mode 100644 UI/basic-controls.cpp create mode 100644 UI/basic-controls.hpp create mode 100644 UI/forms/OBSBasicControls.ui create mode 100644 UI/noncheckable-button.hpp delete mode 100644 UI/record-button.cpp delete mode 100644 UI/record-button.hpp diff --git a/UI/basic-controls.cpp b/UI/basic-controls.cpp new file mode 100644 index 000000000..00145281c --- /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 000000000..6aa677802 --- /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 5351f16f6..dc2800464 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 4b4ccb66e..d3f6f44ec 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 4989d2d11..6148fda88 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 91b48ddc4..f9bc6e07f 100644 --- a/UI/data/themes/Yami.obt +++ b/UI/data/themes/Yami.obt @@ -990,6 +990,14 @@ QPushButton[themeID="replayBufferButton"], 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, diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index a0313b2b4..052d86735 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 000000000..c70df6142 --- /dev/null +++ b/UI/forms/OBSBasicControls.ui @@ -0,0 +1,397 @@ + + + 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 + + + true + + + pauseIconSmall + + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Basic.Main.StartReplayBuffer + + + true + + + replayBufferButton + + + + + + + true + + + + 0 + 0 + + + + Basic.Main.SaveReplay + + + Basic.Main.SaveReplay + + + replayIconSmall + + + + + + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + Basic.Main.StartVirtualCam + + + true + + + vcamButton + + + + + + + true + + + + 0 + 0 + + + + Basic.Main.VirtualCamConfig + + + Basic.Main.VirtualCamConfig + + + 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 000000000..71d942ef3 --- /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 a33bbfdec..000000000 --- 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 ea8d40c7d..000000000 --- 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.cpp b/UI/window-basic-main.cpp index 130259883..74e07e540 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,13 +333,6 @@ OBSBasic::OBSBasic(QWidget *parent) ui->setupUi(this); ui->previewDisabledWidget->setVisible(false); - ui->broadcastButton->setVisible(false); - - /* Setup Studio Mode button connections */ - connect(this, &OBSBasic::PreviewProgramModeChanged, ui->modeSwitch, - &QAbstractButton::setChecked); - connect(ui->modeSwitch, &QAbstractButton::clicked, this, - &OBSBasic::TogglePreviewProgramMode); /* Set up streaming connections */ connect( @@ -378,6 +372,52 @@ OBSBasic::OBSBasic(QWidget *parent) }, 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(); statsDock = new OBSDock(); @@ -518,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 @@ -577,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); @@ -1985,7 +2022,7 @@ void OBSBasic::InitPrimitives() obs_leave_graphics(); } -void OBSBasic::ReplayBufferClicked() +void OBSBasic::ReplayBufferActionTriggered() { if (outputHandler->ReplayBufferActive()) StopReplayBuffer(); @@ -1993,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"); @@ -2019,15 +2043,7 @@ 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( @@ -2169,7 +2185,7 @@ void OBSBasic::OBSInit() vcamEnabled = (obs_get_output_flags(VIRTUAL_CAM_ID) & OBS_OUTPUT_VIDEO) != 0; if (vcamEnabled) { - AddVCamButton(); + emit VirtualCamEnabled(); } InitBasicConfigDefaults2(); @@ -6945,9 +6961,6 @@ void OBSBasic::DisplayStreamStartError() : QTStr("Output.StartFailedGeneric"); emit StreamingStopped(); - ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(false); if (sysTrayStream) { sysTrayStream->setText(QTStr("Basic.Main.StartStreaming")); @@ -6981,6 +6994,8 @@ void OBSBasic::YouTubeActionDialogOk(const QString &broadcast_id, autoStopBroadcast = autostop; broadcastReady = true; + emit BroadcastStreamReady(broadcastReady); + if (start_now) QMetaObject::invokeMethod(this, "StartStreaming"); } @@ -7023,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); @@ -7077,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( @@ -7099,16 +7110,12 @@ void OBSBasic::StartStreaming() } } - emit StreamingStarting(); - ui->streamButton->setEnabled(false); - ui->streamButton->setChecked(false); - ui->broadcastButton->setChecked(false); - if (sysTrayStream) - sysTrayStream->setEnabled(false); + emit StreamingPreparing(); - ui->streamButton->setText("Basic.Main.PreparingStream"); - if (sysTrayStream) + if (sysTrayStream) { + sysTrayStream->setEnabled(false); sysTrayStream->setText("Basic.Main.PreparingStream"); + } auto holder = outputHandler->SetupStreaming(service); auto future = holder.future.then(this, [&](bool setupStreamingResult) { @@ -7122,7 +7129,8 @@ void OBSBasic::StartStreaming() SaveProject(); - ui->streamButton->setText("Basic.Main.Connecting"); + emit StreamingStarting(autoStartBroadcast); + if (sysTrayStream) sysTrayStream->setText("Basic.Main.Connecting"); @@ -7131,32 +7139,8 @@ void OBSBasic::StartStreaming() return; } - 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); + if (autoStartBroadcast) { + emit BroadcastStreamStarted(autoStopBroadcast); broadcastActive = true; } @@ -7185,8 +7169,6 @@ void OBSBasic::BroadcastButtonClicked() if (!broadcastReady || (!broadcastActive && !outputHandler->StreamingActive())) { SetupBroadcast(); - if (broadcastReady) - ui->broadcastButton->setChecked(true); return; } @@ -7210,7 +7192,6 @@ void OBSBasic::BroadcastButtonClicked() this, QTStr("Output.BroadcastStartFailed"), last_error, true); - ui->broadcastButton->setChecked(false); return; } } @@ -7218,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", @@ -7241,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 = @@ -7273,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() @@ -7296,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 } @@ -7433,6 +7392,8 @@ void OBSBasic::StopStreaming() broadcastReady = false; } + emit BroadcastStreamReady(broadcastReady); + OnDeactivate(); bool recordWhenStreaming = config_get_bool( @@ -7473,6 +7434,8 @@ void OBSBasic::ForceStopStreaming() broadcastReady = false; } + emit BroadcastStreamReady(broadcastReady); + OnDeactivate(); bool recordWhenStreaming = config_get_bool( @@ -7494,26 +7457,13 @@ void OBSBasic::ForceStopStreaming() void OBSBasic::StreamDelayStarting(int sec) { - emit StreamingStarted(); - ui->streamButton->setText(QTStr("Basic.Main.StopStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(true); + emit StreamingStarted(true); if (sysTrayStream) { 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(); @@ -7521,26 +7471,13 @@ void OBSBasic::StreamDelayStarting(int sec) void OBSBasic::StreamDelayStopping(int sec) { - emit StreamingStopped(); - ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(false); + emit StreamingStopped(true); if (sysTrayStream) { 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) @@ -7551,10 +7488,6 @@ 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) { @@ -7594,7 +7527,7 @@ void OBSBasic::StreamingStart() void OBSBasic::StreamStopping() { - ui->streamButton->setText(QTStr("Basic.Main.StoppingStreaming")); + emit StreamingStopping(); if (sysTrayStream) sysTrayStream->setText(QTStr("Basic.Main.StoppingStreaming")); @@ -7655,9 +7588,6 @@ void OBSBasic::StreamingStop(int code, QString last_error) ui->statusbar->StreamStopped(); emit StreamingStopped(); - ui->streamButton->setText(QTStr("Basic.Main.StartStreaming")); - ui->streamButton->setEnabled(true); - ui->streamButton->setChecked(false); if (sysTrayStream) { sysTrayStream->setText(QTStr("Basic.Main.StartStreaming")); @@ -7696,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()); @@ -7796,13 +7720,11 @@ void OBSBasic::StartRecording() if (!OutputPathValid()) { OutputPathInvalidMessage(); - ui->recordButton->setChecked(false); return; } if (!IsFFmpegOutputToURL() && LowDiskSpace()) { DiskSpaceMessage(); - ui->recordButton->setChecked(false); return; } @@ -7811,13 +7733,12 @@ 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(QTStr("Basic.Main.StoppingRecording")); @@ -7840,9 +7761,7 @@ void OBSBasic::StopRecording() void OBSBasic::RecordingStart() { ui->statusbar->RecordingStarted(outputHandler->fileOutput); - emit RecordingStarted(); - ui->recordButton->setText(QTStr("Basic.Main.StopRecording")); - ui->recordButton->setChecked(true); + emit RecordingStarted(isRecordingPausable); if (sysTrayRecord) sysTrayRecord->setText(QTStr("Basic.Main.StopRecording")); @@ -7855,7 +7774,6 @@ void OBSBasic::RecordingStart() diskFullTimer->start(1000); OnActivate(); - UpdatePause(); blog(LOG_INFO, RECORDING_START); } @@ -7864,8 +7782,6 @@ void OBSBasic::RecordingStop(int code, QString last_error) { ui->statusbar->RecordingStopped(); emit RecordingStopped(); - ui->recordButton->setText(QTStr("Basic.Main.StartRecording")); - ui->recordButton->setChecked(false); if (sysTrayRecord) sysTrayRecord->setText(QTStr("Basic.Main.StartRecording")); @@ -7935,7 +7851,6 @@ void OBSBasic::RecordingStop(int code, QString last_error) AutoRemux(outputHandler->lastRecordingPath.c_str()); OnDeactivate(); - UpdatePause(false); } void OBSBasic::RecordingFileChanged(QString lastRecordingPath) @@ -7986,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; } @@ -8008,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(); } } @@ -8020,8 +7930,7 @@ void OBSBasic::ReplayBufferStopping() if (!outputHandler || !outputHandler->replayBuffer) return; - replayBufferButton->first()->setText( - QTStr("Basic.Main.StoppingReplayBuffer")); + emit ReplayBufStopping(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText( @@ -8050,9 +7959,7 @@ 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( @@ -8063,7 +7970,6 @@ void OBSBasic::ReplayBufferStart() api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED); OnActivate(); - UpdateReplayBuffer(); blog(LOG_INFO, REPLAY_BUFFER_START); } @@ -8111,9 +8017,7 @@ 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( @@ -8151,7 +8055,6 @@ void OBSBasic::ReplayBufferStop(int code) api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED); OnDeactivate(); - UpdateReplayBuffer(false); } void OBSBasic::StartVirtualCam() @@ -8165,9 +8068,7 @@ void OBSBasic::StartVirtualCam() SaveProject(); - if (!outputHandler->StartVirtualCam()) { - vcamButton->first()->setChecked(false); - } + outputHandler->StartVirtualCam(); } void OBSBasic::StopVirtualCam() @@ -8188,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); @@ -8206,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); @@ -8226,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", @@ -8241,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; } @@ -8257,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(); @@ -8282,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; } @@ -8310,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( @@ -8322,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", @@ -8346,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); @@ -8440,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); @@ -9735,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}; @@ -9743,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); @@ -9768,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--) @@ -10071,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); } @@ -10851,11 +10729,6 @@ void OBSBasic::PauseRecording() os_atomic_set_bool(&recording_paused, true); emit RecordingPaused(); - pause->setAccessibleName(QTStr("Basic.Main.UnpauseRecording")); - pause->setToolTip(QTStr("Basic.Main.UnpauseRecording")); - pause->blockSignals(true); - pause->setChecked(true); - pause->blockSignals(false); ui->statusbar->RecordingPaused(); @@ -10873,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); @@ -10899,11 +10767,6 @@ void OBSBasic::UnpauseRecording() os_atomic_set_bool(&recording_paused, false); emit RecordingUnpaused(); - pause->setAccessibleName(QTStr("Basic.Main.PauseRecording")); - pause->setToolTip(QTStr("Basic.Main.PauseRecording")); - pause->blockSignals(true); - pause->setChecked(false); - pause->blockSignals(false); ui->statusbar->RecordingUnpaused(); @@ -10921,17 +10784,12 @@ 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 (!isRecordingPausable || !outputHandler || !outputHandler->fileOutput) @@ -10973,47 +10831,6 @@ void OBSBasic::UpdateIsRecordingPausable() isRecordingPausable = !shared; } -void OBSBasic::UpdatePause(bool activate) -{ - if (!activate || !outputHandler || !outputHandler->RecordingActive()) { - pause.reset(); - return; - } - - if (isRecordingPausable) { - 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); -} - #define MBYTE (1024ULL * 1024ULL) #define MBYTES_LEFT_STOP_REC 50ULL #define MAX_BYTES_LEFT (MBYTES_LEFT_STOP_REC * MBYTE) diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index a478c49ff..f68075ba3 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -319,13 +319,8 @@ private: QPointer extraBrowsers; QPointer importer; - QPointer startStreamMenu; - QPointer transitionButton; - QPointer replayBufferButton; - QScopedPointer pause; - QPointer vcamButton; bool vcamEnabled = false; VCamConfig vcamConfig; @@ -546,8 +541,6 @@ private: void dragMoveEvent(QDragMoveEvent *event) override; void dropEvent(QDropEvent *event) override; - void ReplayBufferClicked(); - bool sysTrayMinimizeToTray(); void EnumDialogs(); @@ -888,8 +881,6 @@ private: void AutoRemux(QString input, bool no_show = false); void UpdateIsRecordingPausable(); - void UpdatePause(bool activate = true); - void UpdateReplayBuffer(bool activate = true); bool IsFFmpegOutputToURL() const; bool OutputPathValid(); @@ -933,7 +924,6 @@ public: int ResetVideo(); bool ResetAudio(); - void AddVCamButton(); void ResetOutputs(); void RefreshVolumeColors(); @@ -1132,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(); @@ -1198,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); @@ -1241,6 +1224,23 @@ 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(); @@ -1259,22 +1259,44 @@ public slots: signals: /* Streaming signals */ - void StreamingStarting(); - void StreamingStarted(); - void StreamingStopped(); + 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(); + 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`. */