Merge pull request #2203 from JohannMG/streaming-start-validation
UI: Streaming Settings Validation On Stream Start & User Help
This commit is contained in:
commit
d3b6f7a71f
@ -245,6 +245,7 @@ set(obs_SOURCES
|
||||
combobox-ignorewheel.cpp
|
||||
spinbox-ignorewheel.cpp
|
||||
record-button.cpp
|
||||
ui-validation.cpp
|
||||
url-push-button.cpp
|
||||
volume-control.cpp
|
||||
adv-audio-control.cpp
|
||||
@ -302,6 +303,7 @@ set(obs_HEADERS
|
||||
menu-button.hpp
|
||||
mute-checkbox.hpp
|
||||
record-button.hpp
|
||||
ui-validation.hpp
|
||||
url-push-button.hpp
|
||||
volume-control.hpp
|
||||
adv-audio-control.hpp
|
||||
|
@ -679,6 +679,11 @@ Basic.Settings.Stream.TTVAddon.None="None"
|
||||
Basic.Settings.Stream.TTVAddon.BTTV="BetterTTV"
|
||||
Basic.Settings.Stream.TTVAddon.FFZ="FrankerFaceZ"
|
||||
Basic.Settings.Stream.TTVAddon.Both="BetterTTV and FrankerFaceZ"
|
||||
Basic.Settings.Stream.MissingSettingAlert="Missing Stream Setup"
|
||||
Basic.Settings.Stream.StreamSettingsWarning="Open Settings"
|
||||
Basic.Settings.Stream.MissingUrlAndApiKey="URL and Stream Key are missing.\n\nOpen settings to enter the URL and Stream Key in the 'stream' tab."
|
||||
Basic.Settings.Stream.MissingUrl="Stream URL is missing.\n\nOpen settings to enter the URL in the 'Stream' tab."
|
||||
Basic.Settings.Stream.MissingStreamKey="Stream key is missing.\n\nOpen settings to enter the stream key in the 'Stream' tab."
|
||||
|
||||
# basic mode 'output' settings
|
||||
Basic.Settings.Output="Output"
|
||||
|
119
UI/ui-validation.cpp
Normal file
119
UI/ui-validation.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "ui-validation.hpp"
|
||||
|
||||
#include <obs.hpp>
|
||||
#include <QString>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include <obs-app.hpp>
|
||||
#include <obs-service.h>
|
||||
|
||||
static int CountVideoSources()
|
||||
{
|
||||
int count = 0;
|
||||
auto countSources = [](void *param, obs_source_t *source) {
|
||||
if (!source)
|
||||
return true;
|
||||
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
if ((flags & OBS_SOURCE_VIDEO) != 0)
|
||||
(*reinterpret_cast<int *>(param))++;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
obs_enum_sources(countSources, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
bool UIValidation::NoSourcesConfirmation(QWidget *parent)
|
||||
{
|
||||
// There are sources, don't need confirmation
|
||||
if (CountVideoSources() != 0)
|
||||
return true;
|
||||
|
||||
// Ignore no video if no parent is visible to alert on
|
||||
if (!parent->isVisible())
|
||||
return true;
|
||||
|
||||
QString msg = QTStr("NoSources.Text");
|
||||
msg += "\n\n";
|
||||
msg += QTStr("NoSources.Text.AddSource");
|
||||
|
||||
QMessageBox messageBox(parent);
|
||||
messageBox.setWindowTitle(QTStr("NoSources.Title"));
|
||||
messageBox.setText(msg);
|
||||
|
||||
QAbstractButton *yesButton =
|
||||
messageBox.addButton(QTStr("Yes"), QMessageBox::YesRole);
|
||||
messageBox.addButton(QTStr("No"), QMessageBox::NoRole);
|
||||
messageBox.setIcon(QMessageBox::Question);
|
||||
messageBox.exec();
|
||||
|
||||
if (messageBox.clickedButton() != yesButton)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
StreamSettingsAction
|
||||
UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
||||
{
|
||||
// Custom services can user API key in URL or user/pass combo.
|
||||
// So only check there is a URL
|
||||
char const *serviceType = obs_service_get_type(service);
|
||||
bool isCustomUrlService = (strcmp(serviceType, "rtmp_custom") == 0);
|
||||
|
||||
char const *streamUrl = obs_service_get_url(service);
|
||||
char const *streamKey = obs_service_get_key(service);
|
||||
|
||||
bool hasStreamUrl = (streamUrl != NULL && streamUrl[0] != '\0');
|
||||
bool hasStreamKey = ((streamKey != NULL && streamKey[0] != '\0') ||
|
||||
isCustomUrlService);
|
||||
|
||||
if (hasStreamUrl && hasStreamKey)
|
||||
return StreamSettingsAction::ContinueStream;
|
||||
|
||||
QString msg;
|
||||
|
||||
if (!hasStreamUrl && !hasStreamKey) {
|
||||
msg = QTStr("Basic.Settings.Stream.MissingUrlAndApiKey");
|
||||
} else if (!hasStreamKey) {
|
||||
msg = QTStr("Basic.Settings.Stream.MissingStreamKey");
|
||||
} else {
|
||||
msg = QTStr("Basic.Settings.Stream.MissingUrl");
|
||||
}
|
||||
|
||||
QMessageBox messageBox(parent);
|
||||
messageBox.setWindowTitle(
|
||||
QTStr("Basic.Settings.Stream.MissingSettingAlert"));
|
||||
messageBox.setText(msg);
|
||||
|
||||
QPushButton *cancel;
|
||||
QPushButton *settings;
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define ACCEPT_BUTTON QMessageBox::AcceptRole
|
||||
#define REJECT_BUTTON QMessageBox::ResetRole
|
||||
#else
|
||||
#define ACCEPT_BUTTON QMessageBox::NoRole
|
||||
#define REJECT_BUTTON QMessageBox::NoRole
|
||||
#endif
|
||||
settings = messageBox.addButton(
|
||||
QTStr("Basic.Settings.Stream.StreamSettingsWarning"),
|
||||
ACCEPT_BUTTON);
|
||||
cancel = messageBox.addButton(QTStr("Cancel"), REJECT_BUTTON);
|
||||
|
||||
messageBox.setDefaultButton(settings);
|
||||
messageBox.setEscapeButton(cancel);
|
||||
|
||||
messageBox.setIcon(QMessageBox::Warning);
|
||||
messageBox.exec();
|
||||
|
||||
if (messageBox.clickedButton() == settings)
|
||||
return StreamSettingsAction::OpenSettings;
|
||||
if (messageBox.clickedButton() == cancel)
|
||||
return StreamSettingsAction::Cancel;
|
||||
|
||||
return StreamSettingsAction::ContinueStream;
|
||||
}
|
30
UI/ui-validation.hpp
Normal file
30
UI/ui-validation.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
||||
#include <obs.hpp>
|
||||
|
||||
enum class StreamSettingsAction {
|
||||
OpenSettings,
|
||||
Cancel,
|
||||
ContinueStream,
|
||||
};
|
||||
|
||||
class UIValidation : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/* Confirm video about to record or stream has sources. Shows alert
|
||||
* box notifying there are no video sources Returns true if user clicks
|
||||
* "Yes" Returns false if user clicks "No" */
|
||||
static bool NoSourcesConfirmation(QWidget *parent);
|
||||
|
||||
/* Check streaming requirements, shows warning with options to open
|
||||
* settings, cancel stream, or attempt connection anyways. If setup
|
||||
* basics is missing in stream, explain missing fields and offer to
|
||||
* open settings, cancel, or continue. Returns Continue if all
|
||||
* settings are valid. */
|
||||
static StreamSettingsAction
|
||||
StreamSettingsConfirmation(QWidget *parent, OBSService service);
|
||||
};
|
@ -54,6 +54,7 @@
|
||||
#include "display-helpers.hpp"
|
||||
#include "volume-control.hpp"
|
||||
#include "remote-text.hpp"
|
||||
#include "ui-validation.hpp"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
@ -163,25 +164,6 @@ static void AddExtraModulePaths()
|
||||
|
||||
extern obs_frontend_callbacks *InitializeAPIInterface(OBSBasic *main);
|
||||
|
||||
static int CountVideoSources()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
auto countSources = [](void *param, obs_source_t *source) {
|
||||
if (!source)
|
||||
return true;
|
||||
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
if ((flags & OBS_SOURCE_VIDEO) != 0)
|
||||
(*reinterpret_cast<int *>(param))++;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
obs_enum_sources(countSources, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void assignDockToggle(QDockWidget *dock, QAction *action)
|
||||
{
|
||||
auto handleWindowToggle = [action](bool vis) {
|
||||
@ -5600,7 +5582,7 @@ void OBSBasic::StartReplayBuffer()
|
||||
if (disableOutputsRef)
|
||||
return;
|
||||
|
||||
if (!NoSourcesConfirmation()) {
|
||||
if (!UIValidation::NoSourcesConfirmation(this)) {
|
||||
replayBufferButton->setChecked(false);
|
||||
return;
|
||||
}
|
||||
@ -5745,30 +5727,6 @@ void OBSBasic::ReplayBufferStop(int code)
|
||||
OnDeactivate();
|
||||
}
|
||||
|
||||
bool OBSBasic::NoSourcesConfirmation()
|
||||
{
|
||||
if (CountVideoSources() == 0 && isVisible()) {
|
||||
QString msg;
|
||||
msg = QTStr("NoSources.Text");
|
||||
msg += "\n\n";
|
||||
msg += QTStr("NoSources.Text.AddSource");
|
||||
|
||||
QMessageBox messageBox(this);
|
||||
messageBox.setWindowTitle(QTStr("NoSources.Title"));
|
||||
messageBox.setText(msg);
|
||||
QAbstractButton *Yes = messageBox.addButton(
|
||||
QTStr("Yes"), QMessageBox::YesRole);
|
||||
messageBox.addButton(QTStr("No"), QMessageBox::NoRole);
|
||||
messageBox.setIcon(QMessageBox::Question);
|
||||
messageBox.exec();
|
||||
|
||||
if (messageBox.clickedButton() != Yes)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OBSBasic::on_streamButton_clicked()
|
||||
{
|
||||
if (outputHandler->StreamingActive()) {
|
||||
@ -5791,7 +5749,21 @@ void OBSBasic::on_streamButton_clicked()
|
||||
|
||||
StopStreaming();
|
||||
} else {
|
||||
if (!NoSourcesConfirmation()) {
|
||||
if (!UIValidation::NoSourcesConfirmation(this)) {
|
||||
ui->streamButton->setChecked(false);
|
||||
return;
|
||||
}
|
||||
|
||||
auto action =
|
||||
UIValidation::StreamSettingsConfirmation(this, service);
|
||||
switch (action) {
|
||||
case StreamSettingsAction::ContinueStream:
|
||||
break;
|
||||
case StreamSettingsAction::OpenSettings:
|
||||
on_action_Settings_triggered();
|
||||
ui->streamButton->setChecked(false);
|
||||
return;
|
||||
case StreamSettingsAction::Cancel:
|
||||
ui->streamButton->setChecked(false);
|
||||
return;
|
||||
}
|
||||
@ -5852,7 +5824,7 @@ void OBSBasic::on_recordButton_clicked()
|
||||
}
|
||||
StopRecording();
|
||||
} else {
|
||||
if (!NoSourcesConfirmation()) {
|
||||
if (!UIValidation::NoSourcesConfirmation(this)) {
|
||||
ui->recordButton->setChecked(false);
|
||||
return;
|
||||
}
|
||||
|
@ -456,8 +456,6 @@ private:
|
||||
|
||||
void ReceivedIntroJson(const QString &text);
|
||||
|
||||
bool NoSourcesConfirmation();
|
||||
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
QList<QSharedPointer<QDockWidget>> extraBrowserDocks;
|
||||
QList<QSharedPointer<QAction>> extraBrowserDockActions;
|
||||
|
Loading…
x
Reference in New Issue
Block a user