obs-studio/UI/goliveapi-network.cpp

155 lines
4.1 KiB
C++

#include "goliveapi-network.hpp"
#include "goliveapi-censoredjson.hpp"
#include <obs.hpp>
#include <obs-app.hpp>
#include <remote-text.hpp>
#include "multitrack-video-error.hpp"
#include <qstring.h>
#include <string>
#include <QMessageBox>
#include <QThreadPool>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
Qt::ConnectionType BlockingConnectionTypeFor(QObject *object);
void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json,
const GoLiveApi::Config &config)
{
using GoLiveApi::StatusResult;
if (!config.status)
return;
auto &status = *config.status;
if (status.result == StatusResult::Success)
return;
auto warn_continue = [&](QString message) {
bool ret = false;
QMetaObject::invokeMethod(
parent,
[=] {
QMessageBox mb(parent);
mb.setIcon(QMessageBox::Warning);
mb.setWindowTitle(QTStr(
"ConfigDownload.WarningMessageTitle"));
mb.setTextFormat(Qt::RichText);
mb.setText(
message +
QTStr("FailedToStartStream.WarningRetry"));
mb.setStandardButtons(
QMessageBox::StandardButton::Yes |
QMessageBox::StandardButton::No);
return mb.exec() ==
QMessageBox::StandardButton::No;
},
BlockingConnectionTypeFor(parent), &ret);
if (ret)
throw MultitrackVideoError::cancel();
};
auto missing_html = [] {
return QTStr("FailedToStartStream.StatusMissingHTML")
.toStdString();
};
if (status.result == StatusResult::Unknown) {
return warn_continue(
QTStr("FailedToStartStream.WarningUnknownStatus")
.arg(raw_json["status"]["result"]
.dump()
.c_str()));
} else if (status.result == StatusResult::Warning) {
if (config.encoder_configurations.empty()) {
throw MultitrackVideoError::warning(
status.html_en_us.value_or(missing_html())
.c_str());
}
return warn_continue(
status.html_en_us.value_or(missing_html()).c_str());
} else if (status.result == StatusResult::Error) {
throw MultitrackVideoError::critical(
status.html_en_us.value_or(missing_html()).c_str());
}
}
GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url,
const GoLiveApi::PostData &post_data,
const QString &multitrack_video_name)
{
json post_data_json = post_data;
blog(LOG_INFO, "Go live POST data: %s",
censoredJson(post_data_json).toUtf8().constData());
if (url.isEmpty())
throw MultitrackVideoError::critical(
QTStr("FailedToStartStream.MissingConfigURL"));
std::string encodeConfigText;
std::string libraryError;
std::vector<std::string> headers;
headers.push_back("Content-Type: application/json");
bool encodeConfigDownloadedOk = GetRemoteFile(
url.toLocal8Bit(), encodeConfigText,
libraryError, // out params
nullptr,
nullptr, // out params (response code and content type)
"POST", post_data_json.dump().c_str(), headers,
nullptr, // signature
5); // timeout in seconds
if (!encodeConfigDownloadedOk)
throw MultitrackVideoError::warning(
QTStr("FailedToStartStream.ConfigRequestFailed")
.arg(url, libraryError.c_str()));
try {
auto data = json::parse(encodeConfigText);
blog(LOG_INFO, "Go live response data: %s",
censoredJson(data, true).toUtf8().constData());
GoLiveApi::Config config = data;
HandleGoLiveApiErrors(parent, data, config);
return config;
} catch (const json::exception &e) {
blog(LOG_INFO, "Failed to parse go live config: %s", e.what());
throw MultitrackVideoError::warning(
QTStr("FailedToStartStream.FallbackToDefault")
.arg(multitrack_video_name));
}
}
QString MultitrackVideoAutoConfigURL(obs_service_t *service)
{
static const std::optional<QString> cli_url =
[]() -> std::optional<QString> {
auto args = qApp->arguments();
for (int i = 0; i < args.length() - 1; i++) {
if (args[i] == "--config-url" &&
args.length() > (i + 1)) {
return args[i + 1];
}
}
return std::nullopt;
}();
QString url;
if (cli_url.has_value()) {
url = *cli_url;
} else {
OBSDataAutoRelease settings = obs_service_get_settings(service);
url = obs_data_get_string(settings,
"multitrack_video_configuration_url");
}
blog(LOG_INFO, "Go live URL: %s", url.toUtf8().constData());
return url;
}