mirror of
https://github.com/Palakis/obs-websocket.git
synced 2024-08-30 18:12:16 +00:00
313 lines
10 KiB
C++
313 lines
10 KiB
C++
/*
|
|
obs-websocket
|
|
Copyright (C) 2016-2021 Stephane Lepin <stephane.lepin@gmail.com>
|
|
Copyright (C) 2020-2021 Kyle Manning <tt2468@gmail.com>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program. If not, see <https://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
#include <QtWidgets/QMessageBox>
|
|
#include <QDateTime>
|
|
#include <QTime>
|
|
#include <obs-module.h>
|
|
#include <obs.hpp>
|
|
|
|
#include "SettingsDialog.h"
|
|
#include "../obs-websocket.h"
|
|
#include "../Config.h"
|
|
#include "../websocketserver/WebSocketServer.h"
|
|
#include "../utils/Crypto.h"
|
|
|
|
QString GetToolTipIconHtml()
|
|
{
|
|
bool lightTheme = QApplication::palette().text().color().redF() < 0.5;
|
|
QString iconFile = lightTheme ? ":toolTip/images/help.svg" : ":toolTip/images/help_light.svg";
|
|
QString iconTemplate = "<html> <img src='%1' style=' vertical-align: bottom; ' /></html>";
|
|
return iconTemplate.arg(iconFile);
|
|
}
|
|
|
|
SettingsDialog::SettingsDialog(QWidget *parent)
|
|
: QDialog(parent, Qt::Dialog),
|
|
ui(new Ui::SettingsDialog),
|
|
connectInfo(new ConnectInfo),
|
|
sessionTableTimer(new QTimer),
|
|
passwordManuallyEdited(false)
|
|
{
|
|
ui->setupUi(this);
|
|
ui->websocketSessionTable->horizontalHeader()->resizeSection(3, 100); // Resize Session Table column widths
|
|
ui->websocketSessionTable->horizontalHeader()->resizeSection(4, 100);
|
|
|
|
// Remove the ? button on dialogs on Windows
|
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
|
// Set the appropriate tooltip icon for the theme
|
|
ui->enableDebugLoggingToolTipLabel->setText(GetToolTipIconHtml());
|
|
|
|
connect(sessionTableTimer, &QTimer::timeout, this, &SettingsDialog::FillSessionTable);
|
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &SettingsDialog::DialogButtonClicked);
|
|
connect(ui->enableAuthenticationCheckBox, &QCheckBox::stateChanged, this,
|
|
&SettingsDialog::EnableAuthenticationCheckBoxChanged);
|
|
connect(ui->generatePasswordButton, &QPushButton::clicked, this, &SettingsDialog::GeneratePasswordButtonClicked);
|
|
connect(ui->showConnectInfoButton, &QPushButton::clicked, this, &SettingsDialog::ShowConnectInfoButtonClicked);
|
|
connect(ui->serverPasswordLineEdit, &QLineEdit::textEdited, this, &SettingsDialog::PasswordEdited);
|
|
}
|
|
|
|
SettingsDialog::~SettingsDialog()
|
|
{
|
|
delete ui;
|
|
delete connectInfo;
|
|
delete sessionTableTimer;
|
|
}
|
|
|
|
void SettingsDialog::showEvent(QShowEvent *)
|
|
{
|
|
auto conf = GetConfig();
|
|
if (!conf) {
|
|
blog(LOG_ERROR, "[SettingsDialog::showEvent] Unable to retreive config!");
|
|
return;
|
|
}
|
|
|
|
if (conf->PortOverridden)
|
|
ui->serverPortSpinBox->setEnabled(false);
|
|
|
|
if (conf->PasswordOverridden) {
|
|
ui->enableAuthenticationCheckBox->setEnabled(false);
|
|
ui->serverPasswordLineEdit->setEnabled(false);
|
|
ui->generatePasswordButton->setEnabled(false);
|
|
}
|
|
|
|
passwordManuallyEdited = false;
|
|
|
|
RefreshData();
|
|
|
|
sessionTableTimer->start(1000);
|
|
}
|
|
|
|
void SettingsDialog::hideEvent(QHideEvent *)
|
|
{
|
|
if (sessionTableTimer->isActive())
|
|
sessionTableTimer->stop();
|
|
|
|
connectInfo->hide();
|
|
}
|
|
|
|
void SettingsDialog::ToggleShowHide()
|
|
{
|
|
if (!isVisible())
|
|
setVisible(true);
|
|
else
|
|
setVisible(false);
|
|
}
|
|
|
|
void SettingsDialog::RefreshData()
|
|
{
|
|
auto conf = GetConfig();
|
|
if (!conf) {
|
|
blog(LOG_ERROR, "[SettingsDialog::RefreshData] Unable to retreive config!");
|
|
return;
|
|
}
|
|
|
|
ui->enableWebSocketServerCheckBox->setChecked(conf->ServerEnabled);
|
|
ui->enableSystemTrayAlertsCheckBox->setChecked(conf->AlertsEnabled);
|
|
ui->enableDebugLoggingCheckBox->setChecked(conf->DebugEnabled);
|
|
ui->serverPortSpinBox->setValue(conf->ServerPort);
|
|
ui->enableAuthenticationCheckBox->setChecked(conf->AuthRequired);
|
|
ui->serverPasswordLineEdit->setText(conf->ServerPassword);
|
|
|
|
ui->serverPasswordLineEdit->setEnabled(conf->AuthRequired);
|
|
ui->generatePasswordButton->setEnabled(conf->AuthRequired);
|
|
|
|
FillSessionTable();
|
|
}
|
|
|
|
void SettingsDialog::DialogButtonClicked(QAbstractButton *button)
|
|
{
|
|
if (button == ui->buttonBox->button(QDialogButtonBox::Ok)) {
|
|
SaveFormData();
|
|
} else if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) {
|
|
SaveFormData();
|
|
}
|
|
}
|
|
|
|
void SettingsDialog::SaveFormData()
|
|
{
|
|
auto conf = GetConfig();
|
|
if (!conf) {
|
|
blog(LOG_ERROR, "[SettingsDialog::SaveFormData] Unable to retreive config!");
|
|
return;
|
|
}
|
|
|
|
if (ui->serverPasswordLineEdit->text().length() < 6) {
|
|
QMessageBox msgBox;
|
|
msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.PasswordInvalidErrorTitle"));
|
|
msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.PasswordInvalidErrorMessage"));
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
msgBox.exec();
|
|
return;
|
|
}
|
|
|
|
// Show a confirmation box to the user if they attempt to provide their own password
|
|
if (passwordManuallyEdited && (conf->ServerPassword != ui->serverPasswordLineEdit->text())) {
|
|
QMessageBox msgBox;
|
|
msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningTitle"));
|
|
msgBox.setText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningMessage"));
|
|
msgBox.setInformativeText(obs_module_text("OBSWebSocket.Settings.Save.UserPasswordWarningInfoText"));
|
|
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
msgBox.setDefaultButton(QMessageBox::No);
|
|
int ret = msgBox.exec();
|
|
|
|
switch (ret) {
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
default:
|
|
ui->serverPasswordLineEdit->setText(conf->ServerPassword);
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool needsRestart =
|
|
(conf->ServerEnabled != ui->enableWebSocketServerCheckBox->isChecked()) ||
|
|
(conf->ServerPort != ui->serverPortSpinBox->value()) ||
|
|
(ui->enableAuthenticationCheckBox->isChecked() && conf->ServerPassword != ui->serverPasswordLineEdit->text());
|
|
|
|
conf->ServerEnabled = ui->enableWebSocketServerCheckBox->isChecked();
|
|
conf->AlertsEnabled = ui->enableSystemTrayAlertsCheckBox->isChecked();
|
|
conf->DebugEnabled = ui->enableDebugLoggingCheckBox->isChecked();
|
|
conf->ServerPort = ui->serverPortSpinBox->value();
|
|
conf->AuthRequired = ui->enableAuthenticationCheckBox->isChecked();
|
|
conf->ServerPassword = ui->serverPasswordLineEdit->text();
|
|
|
|
conf->Save();
|
|
|
|
RefreshData();
|
|
connectInfo->RefreshData();
|
|
|
|
if (needsRestart) {
|
|
blog(LOG_INFO, "[SettingsDialog::SaveFormData] A setting was changed which requires a server restart.");
|
|
auto server = GetWebSocketServer();
|
|
server->Stop();
|
|
if (conf->ServerEnabled) {
|
|
server->Start();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SettingsDialog::FillSessionTable()
|
|
{
|
|
auto webSocketServer = GetWebSocketServer();
|
|
if (!webSocketServer) {
|
|
blog(LOG_ERROR, "[SettingsDialog::FillSessionTable] Unable to fetch websocket server instance!");
|
|
return;
|
|
}
|
|
|
|
auto webSocketSessions = webSocketServer->GetWebSocketSessions();
|
|
size_t rowCount = webSocketSessions.size();
|
|
|
|
// Manually setting the pixmap size *might* break with highdpi. Not sure though
|
|
QIcon checkIcon = style()->standardIcon(QStyle::SP_DialogOkButton);
|
|
QPixmap checkIconPixmap = checkIcon.pixmap(QSize(25, 25));
|
|
QIcon crossIcon = style()->standardIcon(QStyle::SP_DialogCancelButton);
|
|
QPixmap crossIconPixmap = crossIcon.pixmap(QSize(25, 25));
|
|
|
|
// Todo: Make a util for translations so that we don't need to import a bunch of obs libraries in order to use them.
|
|
QString kickButtonText = obs_module_text("OBSWebSocket.SessionTable.KickButtonText");
|
|
|
|
ui->websocketSessionTable->setRowCount(rowCount);
|
|
size_t i = 0;
|
|
for (auto session : webSocketSessions) {
|
|
QTableWidgetItem *addressItem = new QTableWidgetItem(QString::fromStdString(session.remoteAddress));
|
|
ui->websocketSessionTable->setItem(i, 0, addressItem);
|
|
|
|
uint64_t sessionDuration = QDateTime::currentSecsSinceEpoch() - session.connectedAt;
|
|
QTableWidgetItem *durationItem = new QTableWidgetItem(QTime(0, 0, sessionDuration).toString("hh:mm:ss"));
|
|
ui->websocketSessionTable->setItem(i, 1, durationItem);
|
|
|
|
QTableWidgetItem *statsItem =
|
|
new QTableWidgetItem(QString("%1/%2").arg(session.incomingMessages).arg(session.outgoingMessages));
|
|
ui->websocketSessionTable->setItem(i, 2, statsItem);
|
|
|
|
QLabel *identifiedLabel = new QLabel();
|
|
identifiedLabel->setAlignment(Qt::AlignCenter);
|
|
if (session.isIdentified) {
|
|
identifiedLabel->setPixmap(checkIconPixmap);
|
|
} else {
|
|
identifiedLabel->setPixmap(crossIconPixmap);
|
|
}
|
|
ui->websocketSessionTable->setCellWidget(i, 3, identifiedLabel);
|
|
|
|
QPushButton *invalidateButton = new QPushButton(kickButtonText, this);
|
|
QWidget *invalidateButtonWidget = new QWidget();
|
|
QHBoxLayout *invalidateButtonLayout = new QHBoxLayout(invalidateButtonWidget);
|
|
invalidateButtonLayout->addWidget(invalidateButton);
|
|
invalidateButtonLayout->setAlignment(Qt::AlignCenter);
|
|
invalidateButtonLayout->setContentsMargins(0, 0, 0, 0);
|
|
invalidateButtonWidget->setLayout(invalidateButtonLayout);
|
|
ui->websocketSessionTable->setCellWidget(i, 4, invalidateButtonWidget);
|
|
connect(invalidateButton, &QPushButton::clicked, [=]() { webSocketServer->InvalidateSession(session.hdl); });
|
|
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void SettingsDialog::EnableAuthenticationCheckBoxChanged()
|
|
{
|
|
if (ui->enableAuthenticationCheckBox->isChecked()) {
|
|
ui->serverPasswordLineEdit->setEnabled(true);
|
|
ui->generatePasswordButton->setEnabled(true);
|
|
} else {
|
|
ui->serverPasswordLineEdit->setEnabled(false);
|
|
ui->generatePasswordButton->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
void SettingsDialog::GeneratePasswordButtonClicked()
|
|
{
|
|
QString newPassword = QString::fromStdString(Utils::Crypto::GeneratePassword());
|
|
ui->serverPasswordLineEdit->setText(newPassword);
|
|
ui->serverPasswordLineEdit->selectAll();
|
|
passwordManuallyEdited = false;
|
|
}
|
|
|
|
void SettingsDialog::ShowConnectInfoButtonClicked()
|
|
{
|
|
if (obs_video_active()) {
|
|
QMessageBox msgBox;
|
|
msgBox.setWindowTitle(obs_module_text("OBSWebSocket.Settings.ShowConnectInfoWarningTitle"));
|
|
msgBox.setText(obs_module_text("OBSWebSocket.Settings.ShowConnectInfoWarningMessage"));
|
|
msgBox.setInformativeText(obs_module_text("OBSWebSocket.Settings.ShowConnectInfoWarningInfoText"));
|
|
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
msgBox.setDefaultButton(QMessageBox::No);
|
|
int ret = msgBox.exec();
|
|
|
|
switch (ret) {
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
connectInfo->show();
|
|
connectInfo->activateWindow();
|
|
connectInfo->raise();
|
|
connectInfo->setFocus();
|
|
}
|
|
|
|
void SettingsDialog::PasswordEdited()
|
|
{
|
|
passwordManuallyEdited = true;
|
|
}
|