diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini
index de07d7ddf..2c5bdeb34 100644
--- a/UI/data/locale/en-US.ini
+++ b/UI/data/locale/en-US.ini
@@ -141,6 +141,11 @@ Basic.AutoConfig.VideoPage.FPS.PreferHighRes="Either 60 or 30, but prefer high r
Basic.AutoConfig.VideoPage.CanvasExplanation="Note: The canvas (base) resolution is not necessarily the same as the resolution you will stream or record with. Your actual stream/recording resolution may be scaled down from the canvas resolution to reduce resource usage or bitrate requirements."
Basic.AutoConfig.StreamPage="Stream Information"
Basic.AutoConfig.StreamPage.SubTitle="Please enter your stream information"
+Basic.AutoConfig.StreamPage.ConnectAccount="Connect Account (optional)"
+Basic.AutoConfig.StreamPage.DisconnectAccount="Disconnect Account"
+Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Title="Disconnect Account?"
+Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Text="This change will apply immediately. Are you sure you want to disconnect your account?"
+Basic.AutoConfig.StreamPage.UseStreamKey="Use Stream Key"
Basic.AutoConfig.StreamPage.Service="Service"
Basic.AutoConfig.StreamPage.Service.ShowAll="Show All..."
Basic.AutoConfig.StreamPage.Service.Custom="Custom..."
diff --git a/UI/forms/AutoConfigStreamPage.ui b/UI/forms/AutoConfigStreamPage.ui
index 7389adafe..c52e37979 100644
--- a/UI/forms/AutoConfigStreamPage.ui
+++ b/UI/forms/AutoConfigStreamPage.ui
@@ -79,8 +79,98 @@
-
- 0
+ 1
+
+
+
+ QFormLayout::ExpandingFieldsGrow
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
-
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 87
+ 17
+
+
+
+
+ -
+
+
-
+
+
+ Basic.AutoConfig.StreamPage.ConnectAccount
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 87
+ 17
+
+
+
+
+ -
+
+
-
+
+
+ Basic.AutoConfig.StreamPage.UseStreamKey
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
@@ -294,6 +384,20 @@
+ -
+
+
+ Basic.AutoConfig.StreamPage.ConnectAccount
+
+
+
+ -
+
+
+ Basic.AutoConfig.StreamPage.DisconnectAccount
+
+
+
@@ -301,5 +405,22 @@
-
+
+
+ connectAccount2
+ clicked()
+ connectAccount
+ click()
+
+
+ 382
+ 279
+
+
+ 114
+ 82
+
+
+
+
diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui
index fee71e1da..fc8fed8a9 100644
--- a/UI/forms/OBSBasicSettings.ui
+++ b/UI/forms/OBSBasicSettings.ui
@@ -742,8 +742,92 @@
- 0
+ 1
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 170
+ 19
+
+
+
+
+ -
+
+
-
+
+
+ Basic.AutoConfig.StreamPage.ConnectAccount
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 10
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 170
+ 19
+
+
+
+
+ -
+
+
-
+
+
+ Basic.AutoConfig.StreamPage.UseStreamKey
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
@@ -868,6 +952,54 @@
+ -
+
+
-
+
+
+ Basic.AutoConfig.StreamPage.ConnectAccount
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Basic.AutoConfig.StreamPage.DisconnectAccount
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
@@ -898,8 +1030,8 @@
0
0
- 818
- 697
+ 601
+ 640
@@ -5428,5 +5560,21 @@
+
+ connectAccount2
+ clicked()
+ connectAccount
+ click()
+
+
+ 484
+ 142
+
+
+ 454
+ 87
+
+
+
diff --git a/UI/window-basic-auto-config.cpp b/UI/window-basic-auto-config.cpp
index e05c88d0c..f312b272a 100644
--- a/UI/window-basic-auto-config.cpp
+++ b/UI/window-basic-auto-config.cpp
@@ -12,6 +12,17 @@
#include "ui_AutoConfigVideoPage.h"
#include "ui_AutoConfigStreamPage.h"
+#ifdef BROWSER_AVAILABLE
+#include
+#include "auth-oauth.hpp"
+#endif
+
+struct QCef;
+struct QCefCookieManager;
+
+extern QCef *cef;
+extern QCefCookieManager *panel_cookies;
+
#define wiz reinterpret_cast(wizard())
/* ------------------------------------------------------------------------- */
@@ -222,6 +233,8 @@ AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent)
ui->setupUi(this);
ui->bitrateLabel->setVisible(false);
ui->bitrate->setVisible(false);
+ ui->connectAccount2->setVisible(false);
+ ui->disconnectAccount->setVisible(false);
int vertSpacing = ui->topLayout->verticalSpacing();
@@ -229,6 +242,10 @@ AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent)
m.setBottom(vertSpacing / 2);
ui->topLayout->setContentsMargins(m);
+ m = ui->loginPageLayout->contentsMargins();
+ m.setTop(vertSpacing / 2);
+ ui->loginPageLayout->setContentsMargins(m);
+
m = ui->streamkeyPageLayout->contentsMargins();
m.setTop(vertSpacing / 2);
ui->streamkeyPageLayout->setContentsMargins(m);
@@ -371,6 +388,94 @@ void AutoConfigStreamPage::on_show_clicked()
}
}
+void AutoConfigStreamPage::OnOAuthStreamKeyConnected()
+{
+#ifdef BROWSER_AVAILABLE
+ OAuthStreamKey *a = reinterpret_cast(auth.get());
+
+ if (a) {
+ bool validKey = !a->key().empty();
+
+ if (validKey)
+ ui->key->setText(QT_UTF8(a->key().c_str()));
+
+ ui->streamKeyWidget->setVisible(!validKey);
+ ui->streamKeyLabel->setVisible(!validKey);
+ ui->connectAccount2->setVisible(!validKey);
+ ui->disconnectAccount->setVisible(validKey);
+ }
+
+ ui->stackedWidget->setCurrentIndex((int)Section::StreamKey);
+ UpdateCompleted();
+#endif
+}
+
+void AutoConfigStreamPage::OnAuthConnected()
+{
+ std::string service = QT_TO_UTF8(ui->service->currentText());
+ Auth::Type type = Auth::AuthType(service);
+
+ if (type == Auth::Type::OAuth_StreamKey) {
+ OnOAuthStreamKeyConnected();
+ }
+}
+
+void AutoConfigStreamPage::on_connectAccount_clicked()
+{
+#ifdef BROWSER_AVAILABLE
+ std::string service = QT_TO_UTF8(ui->service->currentText());
+
+ auth = OAuthStreamKey::Login(this, service);
+ if (!!auth)
+ OnAuthConnected();
+#endif
+}
+
+#define DISCONNECT_COMFIRM_TITLE \
+ "Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Title"
+#define DISCONNECT_COMFIRM_TEXT \
+ "Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Text"
+
+void AutoConfigStreamPage::on_disconnectAccount_clicked()
+{
+ QMessageBox::StandardButton button;
+
+ button = OBSMessageBox::question(this,
+ QTStr(DISCONNECT_COMFIRM_TITLE),
+ QTStr(DISCONNECT_COMFIRM_TEXT));
+
+ if (button == QMessageBox::No) {
+ return;
+ }
+
+ OBSBasic *main = OBSBasic::Get();
+
+ main->auth.reset();
+ auth.reset();
+
+ std::string service = QT_TO_UTF8(ui->service->currentText());
+
+#ifdef BROWSER_AVAILABLE
+ OAuth::DeleteCookies(service);
+#endif
+
+ ui->streamKeyWidget->setVisible(true);
+ ui->streamKeyLabel->setVisible(true);
+ ui->connectAccount2->setVisible(true);
+ ui->disconnectAccount->setVisible(false);
+}
+
+void AutoConfigStreamPage::on_useStreamKey_clicked()
+{
+ ui->stackedWidget->setCurrentIndex((int)Section::StreamKey);
+ UpdateCompleted();
+}
+
+static inline bool is_auth_service(const std::string &service)
+{
+ return Auth::AuthType(service) != Auth::Type::None;
+}
+
void AutoConfigStreamPage::ServiceChanged()
{
bool showMore =
@@ -384,6 +489,32 @@ void AutoConfigStreamPage::ServiceChanged()
bool testBandwidth = ui->doBandwidthTest->isChecked();
bool custom = IsCustom();
+ ui->disconnectAccount->setVisible(false);
+
+#ifdef BROWSER_AVAILABLE
+ if (cef) {
+ if (lastService != service.c_str()) {
+ bool can_auth = is_auth_service(service);
+ int page = can_auth
+ ? (int)Section::Connect
+ : (int)Section::StreamKey;
+
+ ui->stackedWidget->setCurrentIndex(page);
+ ui->streamKeyWidget->setVisible(true);
+ ui->streamKeyLabel->setVisible(true);
+ ui->connectAccount2->setVisible(can_auth);
+ auth.reset();
+
+ if (lastService.isEmpty())
+ lastService = service.c_str();
+ }
+ } else {
+ ui->connectAccount2->setVisible(false);
+ }
+#else
+ ui->connectAccount2->setVisible(false);
+#endif
+
/* Test three closest servers if "Auto" is available for Twitch */
if (service == "Twitch" && wiz->twitchAuto)
regionBased = false;
@@ -415,6 +546,17 @@ void AutoConfigStreamPage::ServiceChanged()
ui->bitrateLabel->setHidden(testBandwidth);
ui->bitrate->setHidden(testBandwidth);
+#ifdef BROWSER_AVAILABLE
+ OBSBasic *main = OBSBasic::Get();
+ auth.reset();
+
+ if (!!main->auth &&
+ service.find(main->auth->service()) != std::string::npos) {
+ auth = main->auth;
+ OnAuthConnected();
+ }
+#endif
+
UpdateCompleted();
}
@@ -544,7 +686,8 @@ void AutoConfigStreamPage::UpdateServerList()
void AutoConfigStreamPage::UpdateCompleted()
{
- if (ui->key->text().isEmpty()) {
+ if (ui->stackedWidget->currentIndex() == (int)Section::Connect ||
+ (ui->key->text().isEmpty() && !auth)) {
ready = false;
} else {
bool custom = IsCustom();
@@ -802,6 +945,9 @@ void AutoConfig::SaveStreamSettings()
main->SetService(newService);
main->SaveService();
+ main->auth = streamPage->auth;
+ if (!!main->auth)
+ main->auth->LoadUI();
/* ---------------------------------- */
/* save stream settings */
diff --git a/UI/window-basic-auto-config.hpp b/UI/window-basic-auto-config.hpp
index b51866b14..9426a7548 100644
--- a/UI/window-basic-auto-config.hpp
+++ b/UI/window-basic-auto-config.hpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -18,6 +19,7 @@ class Ui_AutoConfigStreamPage;
class Ui_AutoConfigTestPage;
class AutoConfigStreamPage;
+class Auth;
class AutoConfig : public QWizard {
Q_OBJECT
@@ -160,9 +162,12 @@ class AutoConfigStreamPage : public QWizardPage {
friend class AutoConfig;
enum class Section : int {
+ Connect,
StreamKey,
};
+ std::shared_ptr auth;
+
Ui_AutoConfigStreamPage *ui;
QString lastService;
bool ready = false;
@@ -178,8 +183,14 @@ public:
virtual int nextId() const override;
virtual bool validatePage() override;
+ void OnAuthConnected();
+ void OnOAuthStreamKeyConnected();
+
public slots:
void on_show_clicked();
+ void on_connectAccount_clicked();
+ void on_disconnectAccount_clicked();
+ void on_useStreamKey_clicked();
void ServiceChanged();
void UpdateKeyLink();
void UpdateServerList();
diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp
index 109012579..50aac4feb 100644
--- a/UI/window-basic-main.hpp
+++ b/UI/window-basic-main.hpp
@@ -118,6 +118,8 @@ class OBSBasic : public OBSMainWindow {
friend class OBSBasicSourceSelect;
friend class OBSBasicSettings;
friend class Auth;
+ friend class AutoConfig;
+ friend class AutoConfigStreamPage;
friend struct OBSStudioAPI;
enum class MoveDir {
diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp
index ad1f67fbe..3a28aff40 100644
--- a/UI/window-basic-settings-stream.cpp
+++ b/UI/window-basic-settings-stream.cpp
@@ -5,12 +5,24 @@
#include "window-basic-main.hpp"
#include "qt-wrappers.hpp"
+#ifdef BROWSER_AVAILABLE
+#include
+#include "auth-oauth.hpp"
+#endif
+
+struct QCef;
+struct QCefCookieManager;
+
+extern QCef *cef;
+extern QCefCookieManager *panel_cookies;
+
enum class ListOpt : int {
ShowAll = 1,
Custom,
};
enum class Section : int {
+ Connect,
StreamKey,
};
@@ -21,12 +33,19 @@ inline bool OBSBasicSettings::IsCustomService() const
void OBSBasicSettings::InitStreamPage()
{
+ ui->connectAccount2->setVisible(false);
+ ui->disconnectAccount->setVisible(false);
+
int vertSpacing = ui->topStreamLayout->verticalSpacing();
QMargins m = ui->topStreamLayout->contentsMargins();
m.setBottom(vertSpacing / 2);
ui->topStreamLayout->setContentsMargins(m);
+ m = ui->loginPageLayout->contentsMargins();
+ m.setTop(vertSpacing / 2);
+ ui->loginPageLayout->setContentsMargins(m);
+
m = ui->streamkeyPageLayout->contentsMargins();
m.setTop(vertSpacing / 2);
ui->streamkeyPageLayout->setContentsMargins(m);
@@ -124,6 +143,9 @@ void OBSBasicSettings::SaveStream1Settings()
main->SetService(newService);
main->SaveService();
+ main->auth = auth;
+ if (!!main->auth)
+ main->auth->LoadUI();
}
void OBSBasicSettings::UpdateKeyLink()
@@ -203,6 +225,11 @@ void OBSBasicSettings::LoadServices(bool showAll)
ui->service->blockSignals(false);
}
+static inline bool is_auth_service(const std::string &service)
+{
+ return Auth::AuthType(service) != Auth::Type::None;
+}
+
void OBSBasicSettings::on_service_currentIndexChanged(int)
{
bool showMore =
@@ -213,6 +240,29 @@ void OBSBasicSettings::on_service_currentIndexChanged(int)
std::string service = QT_TO_UTF8(ui->service->currentText());
bool custom = IsCustomService();
+ ui->disconnectAccount->setVisible(false);
+
+#ifdef BROWSER_AVAILABLE
+ if (cef) {
+ if (lastService != service.c_str()) {
+ QString key = ui->key->text();
+ bool can_auth = is_auth_service(service);
+ int page = can_auth && (!loading || key.isEmpty())
+ ? (int)Section::Connect
+ : (int)Section::StreamKey;
+
+ ui->streamStackWidget->setCurrentIndex(page);
+ ui->streamKeyWidget->setVisible(true);
+ ui->streamKeyLabel->setVisible(true);
+ ui->connectAccount2->setVisible(can_auth);
+ }
+ } else {
+ ui->connectAccount2->setVisible(false);
+ }
+#else
+ ui->connectAccount2->setVisible(false);
+#endif
+
if (custom) {
ui->streamkeyPageLayout->insertRow(1, ui->serverLabel,
ui->serverStackedWidget);
@@ -223,6 +273,16 @@ void OBSBasicSettings::on_service_currentIndexChanged(int)
} else {
ui->serverStackedWidget->setCurrentIndex(0);
}
+
+#ifdef BROWSER_AVAILABLE
+ auth.reset();
+
+ if (!!main->auth &&
+ service.find(main->auth->service()) != std::string::npos) {
+ auth = main->auth;
+ OnAuthConnected();
+ }
+#endif
}
void OBSBasicSettings::UpdateServerList()
@@ -298,3 +358,88 @@ OBSService OBSBasicSettings::SpawnTempService()
return newService;
}
+
+void OBSBasicSettings::OnOAuthStreamKeyConnected()
+{
+#ifdef BROWSER_AVAILABLE
+ OAuthStreamKey *a = reinterpret_cast(auth.get());
+
+ if (a) {
+ bool validKey = !a->key().empty();
+
+ if (validKey)
+ ui->key->setText(QT_UTF8(a->key().c_str()));
+
+ ui->streamKeyWidget->setVisible(!validKey);
+ ui->streamKeyLabel->setVisible(!validKey);
+ ui->connectAccount2->setVisible(!validKey);
+ ui->disconnectAccount->setVisible(validKey);
+ }
+
+ ui->streamStackWidget->setCurrentIndex((int)Section::StreamKey);
+#endif
+}
+
+void OBSBasicSettings::OnAuthConnected()
+{
+ std::string service = QT_TO_UTF8(ui->service->currentText());
+ Auth::Type type = Auth::AuthType(service);
+
+ if (type == Auth::Type::OAuth_StreamKey) {
+ OnOAuthStreamKeyConnected();
+ }
+
+ if (!loading) {
+ stream1Changed = true;
+ EnableApplyButton(true);
+ }
+}
+
+void OBSBasicSettings::on_connectAccount_clicked()
+{
+#ifdef BROWSER_AVAILABLE
+ std::string service = QT_TO_UTF8(ui->service->currentText());
+
+ auth = OAuthStreamKey::Login(this, service);
+ if (!!auth)
+ OnAuthConnected();
+#endif
+}
+
+#define DISCONNECT_COMFIRM_TITLE \
+ "Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Title"
+#define DISCONNECT_COMFIRM_TEXT \
+ "Basic.AutoConfig.StreamPage.DisconnectAccount.Confirm.Text"
+
+void OBSBasicSettings::on_disconnectAccount_clicked()
+{
+ QMessageBox::StandardButton button;
+
+ button = OBSMessageBox::question(this,
+ QTStr(DISCONNECT_COMFIRM_TITLE),
+ QTStr(DISCONNECT_COMFIRM_TEXT));
+
+ if (button == QMessageBox::No) {
+ return;
+ }
+
+ main->auth.reset();
+ auth.reset();
+
+ std::string service = QT_TO_UTF8(ui->service->currentText());
+
+#ifdef BROWSER_AVAILABLE
+ OAuth::DeleteCookies(service);
+#endif
+
+ ui->streamKeyWidget->setVisible(true);
+ ui->streamKeyLabel->setVisible(true);
+ ui->connectAccount2->setVisible(true);
+ ui->disconnectAccount->setVisible(false);
+ ui->key->setText("");
+}
+
+void OBSBasicSettings::on_useStreamKey_clicked()
+{
+ ui->streamStackWidget->setCurrentIndex((int)Section::StreamKey);
+}
diff --git a/UI/window-basic-settings.hpp b/UI/window-basic-settings.hpp
index 3f913d669..e3c7ccd56 100644
--- a/UI/window-basic-settings.hpp
+++ b/UI/window-basic-settings.hpp
@@ -28,6 +28,8 @@
#include
+#include "auth-base.hpp"
+
class OBSBasic;
class QAbstractButton;
class QComboBox;
@@ -91,6 +93,8 @@ private:
std::unique_ptr ui;
+ std::shared_ptr auth;
+
bool generalChanged = false;
bool stream1Changed = false;
bool outputsChanged = false;
@@ -211,11 +215,16 @@ private:
void InitStreamPage();
inline bool IsCustomService() const;
void LoadServices(bool showAll);
+ void OnOAuthStreamKeyConnected();
+ void OnAuthConnected();
QString lastService;
private slots:
void UpdateServerList();
void UpdateKeyLink();
void on_show_clicked();
+ void on_connectAccount_clicked();
+ void on_disconnectAccount_clicked();
+ void on_useStreamKey_clicked();
private:
/* output */